Skip to main content

Errors

Every non-2xx response uses the same envelope. Agents branch on error.type (a stable 10-value enum); each error carries nextActions[] — concrete steps to surface to the user.

Envelope shape

Field guarantees

The 10 error types

Recovery matrix

Stable code reference

Every code below is emitted by production code today. Agents may branch on code for finer-grained handling than type.

Auth (401 / 403)

Validation (400 / 410 / 413 / 422)

Not found (404)

Conflicts (409)

Plan / paywall (402)

Rate limit (429)

ToS (451)

Service / internal (500 / 503)

What NOT to do

  • Do not branch on error.message — it’s localized via Accept-Language and may change. Branch on error.type (enum) and error.code (string).
  • Do not swallow nextActions[]. The most common agent-failure mode is silently retrying past a 402 (paywall) or 451 (ToS) without ever showing the user the action.
  • Do not auto-accept the ToS on the user’s behalf. The 451 → modal flow requires user input by design.
  • Do not retry invalid_request with the same body. Fix the body first.
  • Do not branch on HTTP status alone. Several types share a status (409 for two conflict shapes; 404 for both real-missing and cross-tenant). The type + code pair disambiguates.

Verification in code

  • src/api/contracts/error.zod.ts — the locked envelope schema (10 type values).
  • src/api/api-error.ts — the ApiError class that wires status + type + code + recovery hints.
  • src/api/middleware/errors.ts — the global error handler that emits the envelope.