code, not parse the human message.
The envelope
retryable is honest: the CLI auto-retries a GET once on a transient failure but never re-sends a write, and never retries a 4xx. If you build your own client, do the same.Why a code at all
Input that’s wrong shouldn’t reach the agent as an opaque 500. Two layers guarantee that:
- Validation rejects a bad enum (
status,visibility) with a field-level400before it touches the database. - A Postgres-error translator catches any constraint violation that slips through and turns it into a coded
4xx, never a generic500.
500 means what it should: a real bug or an outage. That’s also the only time retryable is true.
Code catalog
Validation & input
Access & identity
Governance & conflicts
Commercial allowance
These errors include the current
usage snapshot and an actionable
next_action for contacting sales. They are definitive (retryable: false).
Server
Observability
Every captured error is also emitted to PostHog (request_failed server-side, command_failed from the CLI) with code, status_code, and endpoint as properties, so the error surface is one queryable map, sliceable by type and endpoint rather than free-text. The exception text itself never leaves the log — join on request_id.