Skip to content

Troubleshooting

When a run fails, crab’d updates its tracking comment with what happened, what to change, and a link back here — instead of a raw stack trace. This page expands on each failure it can post.

Every failure comment names the specific config knob to adjust. The knobs live under limits and rate_limit in your .crabd.yml (or the equivalent in crabd.config.ts).

crab’d stopped … — it reached the tool-call limit before finishing.

Every run has a hard ceiling on tool-calling turns (limits.max_turns, default 40). When a run reaches it, crab’d is stopped mid-task. This is a safety valve against runaway loops and unbounded CI cost — it is not injected into the prompt, so the model isn’t biased into stopping early.

Before it stops, crab’d reserves a few turns to ask the model for a best-effort final answer — so the comment usually carries a partial result (what it found, what’s still open) rather than nothing. When it does, the comment is marked as partial.

Common causes:

  • The task was too broad for one run — e.g. “review this” on a PR touching dozens of files, or an open-ended “look into X”.
  • crab’d chased something it couldn’t finish — most often a file or another repository it has no access to (its token is scoped to the current repo), then looped retrying.

What to change:

  1. Narrow the request. Point crab’d at the specific files or the specific change you want feedback on, or split a large PR into smaller ones.

  2. Raise the ceiling only if the task genuinely needs more steps:

    limits:
    max_turns: 80 # default 40

Raising max_turns trades CI minutes (and tokens) for headroom — prefer narrowing the task first.

crab’d ran out of time … — the run exceeded its time limit.

A wall-clock limit (limits.timeout_minutes) was set and the run exceeded it. Unlike the turn limit, this is off by default — you only see it if you configured it.

What to change:

limits:
timeout_minutes: 20 # raise, or remove to disable

If runs routinely approach the limit, also consider narrowing the request (see above) or a faster model for the mode.

crab’d … every model was rate-limited …

The provider rate-limited or overloaded crab’d, and every model in the fallback chain was exhausted (or the wait budget ran out). This has its own tuning surface — backoff, an ordered fallback-model chain, a wait budget, and per-mode soft/fail behavior. See Rate limiting & fallback models.

crab’d couldn’t start … — its configuration is invalid.

crab’d couldn’t load or validate your config. The details block names the offending field. Check it against the .crabd.yml reference or crabd.config.ts reference, and see Config layering & governance if a value isn’t taking effect (a higher layer may override or forbid it).

the agent can’t read another repository you granted with repos.read

Most often the token can’t reach it. repos.read needs a cross-repo-capable token: your own App (CRABD_APP_*, installed on those repos) or a scoped PAT. Under the default token broker — which vends single-repo tokens by design — repos.read is ignored (the run logs this). Check the run logs, and see Cross-repo access & private registries.

pnpm install / npm install can’t authenticate

Confirm the secret is mapped to an env var on the crab’d step (env: { NPM_TOKEN: ${{ secrets.… }} }), that the same name is what the sandbox.npmrc entry’s token_env references (or is listed in sandbox.env for a non-registry secret), and that the registry URL/scope match your dependency. A name mismatch between the step’s env, token_env, and the secret is the most common cause. See Cross-repo access & private registries.

crab’d logs a warning when it can’t resolve a registry token — sandbox.npmrc: token env "NPM_TOKEN" is not set … — and tells the agent that registry is unauthenticated so it reviews from source instead of thrashing on install retries (a missing token otherwise burns a whole run’s tool budget on 401/403s). If you see that warning, the token never reached the step. Note the forge-token fallback (omitting token_env for same-org GitHub Packages) needs your own GitHub App with packages: read — it does not work under the hosted broker; use an explicit token_env there.

the reply ends with I did not commit anything…, or a commit fails with Resource not accessible by integration

Three reasons, in order of likelihood:

  • The mention didn’t ask for a change. mention mode commits only when the comment asks for one. A bare /crabd, or a question, gets an answer even if crab’d noticed a fix worth making. Ask for the change explicitly.
  • Writes are off. Either permissions.write: false, or modes.implement.enabled: false, which turns writes off everywhere unless you set permissions.write: true. See permissions.
  • The token can’t write. Your GitHub App installation grants contents: read. crab’d now detects this at startup, warns, and runs read-only instead of failing at the commit, and the run log carries the warning. Grant the App Contents: Read and write, then accept the permission request on the installation (an org owner has to approve it; raising the App’s permissions alone does nothing until the installation accepts). Older versions surfaced this only as a 403 from POST /repos/…/git/blobs at the very end of a run.

crab’d hit an error …

A failure that doesn’t fall into the categories above. The comment includes a collapsed Error details block and a link to the run logs — start there. If it looks like a bug in crab’d, please open an issue.

No comment, no 👀 reaction, no failure message. crab’d posts a comment for every failure it can attribute, so silence means it never got far enough to have anything to say. In order of likelihood:

  • The job never ran. Check the run in your forge’s Actions tab. A job showing skipped means its if: was false, not that crab’d declined. Note that in a Forgejo reusable workflow the parent job still reports success when the inner job skips, so the run looks green. See the github.event_name caveat.
  • The event isn’t one crab’d handles. The logs end with event "…" is not handled. Skipping. crab’d acts on pull_request, issue_comment, pull_request_review_comment, and issues only. A push, for example, is a deliberate no-op.
  • No trigger matched. A comment must contain the trigger phrase, and a pull_request only auto-reviews on opened / reopened / ready_for_review, not on a push to the branch. Mention /crabd review to re-review.
  • The pull request is a draft. Draft PRs are never auto-reviewed. Mark the PR ready for review, or mention /crabd review in it.
  • The actor was filtered. Bots never trigger crab’d (to avoid comment loops), and the actor’s association must be in permissions.allowed_associations.