Errors and exit codes
Envelope
Section titled “Envelope”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. |
Codes by HTTP status
Section titled “Codes by HTTP status”| 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.
Reserved codes
Section titled “Reserved codes”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
200with{"granted": false, "needs_you": true}. - Overload surfaces as
503 UNAVAILABLEwithdetails.reason: "writer_queue_full". - Enforcement gaps appear in the doctor
enforcement_gapslist, not as error envelopes.
CLI exit codes
Section titled “CLI exit codes”| 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).