Skip to content

Errors and exit codes

Every error response has exactly this shape:

{"error": {"code": "TASK_OWNED", "message": "...", "request_id": "req-7f3a", "retryable": false, "details": {}}}
Field Meaning
code Stable machine-readable code. Branch on this, not on the message.
message The problem, the affected resource and the safe next step. Never tokens, secrets or stack traces.
request_id Always present, for log correlation.
retryable True only for 429 and 503 class codes. Retries reuse the same Idempotency-Key.
details Optional context such as holder, current revision or cursor. Never secrets.
Status Meaning Codes
400 Validation BAD_REQUEST, INVALID_TRANSITION, DEPENDENCY_CYCLE, ARTIFACT_MISMATCH, SELF_REVIEW_FORBIDDEN, IDENTITY_AMBIGUOUS, INCOMPATIBLE_VERSION
401 Authentication UNAUTHORIZED, IDENTITY_REQUIRED
403 Authority FORBIDDEN, POLICY_DENIED, CAPABILITY_UNAVAILABLE
404 Missing NOT_FOUND
409 Revision or conflict CONFLICT, STALE_REVISION, TASK_OWNED, LEASE_CONFLICT, ASK_PENDING, IDEMPOTENCY_MISMATCH, VERIFICATION_FAILED, RESOURCE_QUARANTINED
410 Gone or resync GONE, RESYNC_REQUIRED
413 Limits PAYLOAD_TOO_LARGE
429 Limits RATE_LIMITED
503 Unavailable UNAVAILABLE, ENFORCEMENT_GAP, TIMEOUT, OUTCOME_UNKNOWN, DAEMON_UNREACHABLE
500 Internal INTERNAL (generic message only)

A 409 preserves the caller’s draft and returns current state. Retry deliberately, never automatically for permission errors or conflicts.

ASK_PENDING, RATE_LIMITED and ENFORCEMENT_GAP are reserved and currently not emitted. Clients must keep accepting them.

  • An ask pause is not an error: admission answers 200 with {"granted": false, "needs_you": true}.
  • Overload surfaces as 503 UNAVAILABLE with details.reason: "writer_queue_full".
  • Enforcement gaps appear in the doctor enforcement_gaps list, not as error envelopes.
Exit Meaning
0 Success, including a completed wait with matched:false.
1 Internal or unclassified failure.
2 Invalid usage, configuration or validation, including ambiguous identity and incompatible API version.
3 Conflict, stale revision, idempotency mismatch or resync required.
4 Authentication or authority denial, missing identity or resource, unavailable capability.
5 Unavailable service, transport timeout, uncertain outcome, quarantine or overload.
6 Verification failed.
130 Interrupted.

Distinct errors can share an exit code, so read error.code too. Hook scripts follow their harness’s denial convention instead (for example, Claude pre-write exit 2).