<!--
Sitemap:
- [Installation](/installation)
- [Upgrading](/upgrading): Version-specific steps for upgrading an existing Bento install.
- [Concepts](/concepts)
- [Build your first pipeline](/tutorials/pipeline-args)
- [Target a specific issue or PR from a URL](/tutorials/url-targeting)
- [Keep state across runs](/tutorials/pipeline-state)
- [Fire a pipeline on a schedule or on demand](/tutorials/schedule-and-fire)
- [Deploy a box to Railway](/tutorials/deploy-to-railway)
- [Operate a hosted daemon](/tutorials/operate-a-hosted-daemon)
- [Configuration](/configuration)
- [Members](/members)
- [Knowledge base](/knowledge-base/)
- [Method and delivery](/knowledge-base/modes)
- [Config](/knowledge-base/config)
- [MCP](/knowledge-base/mcp)
- [Pipeline configuration reference](/pipelines/config)
- [Filters](/pipelines/filters)
- [Triggers](/triggers/)
- [GitHub trigger](/triggers/github)
- [Linear trigger](/triggers/linear)
- [Webhook trigger](/triggers/webhook)
- [Schedule trigger](/triggers/schedule)
- [Manual trigger](/triggers/manual)
- [Traces](/pipelines/traces)
- [Slack](/integrations/slack)
- [Public access](/public-access)
- [Context engineering](/context-engineering)
- [Best practices](/best-practices)
- [Troubleshooting](/troubleshooting)
- [Architecture](/architecture/vision)
- [Workspaces](/workspaces)
- [Authentication](/authentication)
- [Identity](/identity)
- [Security](/security)
- [References](/references)
- [Changelog](/changelog): Bento release history.
- [CLI reference](/cli/)
- [Setup](/cli/setup)
- [Secrets](/cli/secrets)
- [Lifecycle](/cli/lifecycle)
- [Sandbox image](/cli/image)
- [Sandboxes](/cli/sandbox)
- [Observability](/cli/observability)
- [Diagnostics](/cli/diagnostics)
- [Triggers](/cli/triggers)
- [Workbench](/cli/workbench)
- [Auth](/cli/auth)
- [Knowledge](/cli/knowledge)
- [Evals](/cli/evals)
- [Bento](/index)
- [Runtime wrapper](/architecture/runtime-wrapper)
- [Skill evolve](/architecture/skill-evolve)
-->

# Troubleshooting

Each section describes a symptom and the checks that identify its cause. Start with `bento doctor`, which covers the most common failures in one command.

## Start here: `bento doctor`

```bash
bento doctor
```

The command checks the daemon process, the database connection, the availability of `cloudflared` and `tailscale`, and webhook reachability. It exits with a plain-text description of each failure it finds.

***

## Daemon won't start

**Symptom:** `bento daemon start` exits immediately or `bento daemon status` shows the daemon as unreachable.

1. Check the daemon log:
   ```bash
   bento daemon logs
   ```
2. Common causes:
   * **Port 7890 already in use** — `lsof -i :7890` to find the occupant
   * **Database unreachable** — confirm Postgres is running: `docker compose ps`
   * **Missing `GITHUB_WEBHOOK_SECRET`** — set the variable in your shell or `.env` file before `bento daemon start`

***

## Webhooks not firing

**Symptom:** You open a PR and the daemon receives nothing.

1. Confirm the daemon is reachable from the internet:
   ```bash
   bento doctor
   ```
2. Check the GitHub webhook delivery log (repo **Settings → Webhooks → Recent Deliveries**). Look for HTTP errors or timeouts.
3. If you are using a Cloudflare Quick Tunnel, the URL rotates on restart — re-register it with GitHub after every `bento daemon restart`.
4. Confirm the webhook secret in GitHub matches `webhooks.sources.github.secret` in `daemon.yaml`. A mismatch returns `401`. GitHub records the failure in the delivery log.
5. Check daemon logs for signature verification errors:
   ```bash
   bento daemon logs -f
   ```

***

## Agent run not appearing

**Symptom:** GitHub delivered a webhook and shows `200`, but no agent run appears.

1. Check the pipeline trigger matches the event type. `pull_request.opened` and `pull_request.synchronize` are the most common:
   ```bash
   bento trace <event-id>
   ```
2. Check the queue depth. A backlog delays the run:
   ```bash
   bento queue status
   ```
3. Check the concurrency of the worker pool. Daytona and Cloudflare runs use `queue.remote.concurrency`. Local backends use `queue.host.concurrency`. A full pool delays its next eligible job until a worker becomes free.
4. If `bento queue status` shows jobs `waiting` and no job `active` for a long time, run `bento daemon restart`. A restart starts new queue workers. The daemon also restarts itself after [`queue.circuit_breaker.stall_after`](/configuration#queue), which is `15m` by default. Before it restarts, it sends a message to the `escalate` targets.

***

## Agent run failed or timed out

**Symptom:** The run appears in `bento daemon status` but shows `failed` or `timeout`.

1. Read the agent's stdout:
   ```bash
   bento daemon logs <run-id>
   ```
2. Increase `guardrails.timeout` in the pipeline file.
3. Check for sandbox problems. An agent that fails to clone the repository or to reach the network fails early:
   ```bash
   bento probe <invocation-id>
   ```
4. Check `queue.circuit_breaker.failure_threshold` — repeated failures open the circuit and pause queuing for that pipeline.

***

## Authentication failures

**Symptom:** the daemon returns `401 Unauthorized`, or the MCP client fails to connect.

1. List issued tokens:
   ```bash
   bento token list
   ```
2. Verify the token your client is using matches one of the listed IDs.
3. Confirm the `scopes` of the token permit the operation, for example `pipelines:invoke` for a pipeline invocation.
4. Re-issue a token if needed:
   ```bash
   bento token issue --email you@example.com
   ```

See [Authentication](/authentication) for client setup.

***

## Tunnel not reachable

**Symptom:** `bento daemon status` shows `tunnel : pending` or `tunnel : error`.

**Cloudflare Quick Tunnel:**

* Confirm `cloudflared` is on PATH: `which cloudflared`
* The tunnel takes up to 5 seconds to establish after `bento daemon start`. Run `bento daemon status` again after a few seconds.
* Check daemon logs for `cloudflared` errors:
  ```bash
  bento daemon logs | grep tunnel
  ```

**Cloudflare named tunnel:**

* The daemon reports the tunnel ready only after `cloudflared` registers a connection and the public hostname answers `/health` with this daemon's own boot identifier. Both take a few seconds after `bento daemon start`.
* Read the reason from the daemon log: `bento daemon logs | grep tunnel`. It names the part that is missing.
* `no public hostname for tunnel` means neither `~/.cloudflared/config.yml` nor the Cloudflare DNS API gives a hostname. Run `cloudflared tunnel route dns <name> <hostname>`, or add an `ingress` rule to `~/.cloudflared/config.yml`.
* `config.yml could not be parsed` means the file itself is malformed. Fix the YAML; the daemon does not fall back to the DNS API when it cannot read the config.
* A hostname that does not answer means the DNS record does not reach this tunnel. Compare the CNAME target against the tunnel UUID from `cloudflared tunnel info <name>`.
* `is served by daemon <id>, not this one` means the hostname answers, but a different Bento daemon is behind it. The DNS record points at another tunnel, or another host still serves the name. Compare the CNAME target against the tunnel UUID from `cloudflared tunnel info <name>`.

**Tailscale Funnel:**

* Confirm the host is enrolled in your tailnet: `tailscale status`
* Confirm HTTPS certificates are enabled in the Tailscale admin console (**DNS → HTTPS Certificates**)
* Confirm Funnel is enabled (**Access Controls → Funnel**)
* Run `tailscale funnel status` to verify the funnel is active

***

## Database issues

**Symptom:** `database unreachable` in `bento doctor`.

```bash
docker compose ps         # is the container running?
docker compose up -d      # restart if stopped
```

The canonical Compose file sets up Postgres at `postgresql://bento:bento@localhost:8421/bento`. Confirm this matches `database.url` in `daemon.yaml`.

***

## Inspecting a specific run

For deep inspection of a single invocation — agent stdout, prompt, context, and timing — see [Traces](/pipelines/traces).
