Skip to content

Error Reference

All error responses use a standard JSON envelope:

{
"error": {
"code": "snake_case_string",
"message": "Human-readable message",
"details": { ... },
"timestamp": "2026-05-12T10:30:00Z",
"trace_id": "uuid-v4"
}
}

Always present: code, message, timestamp, trace_id. details is omitted unless the error includes structured context.

Build your error-handling logic on codemessage text can change.


Summary Table

CategoryCodesHTTP
Validationvalidation_error, bad_request, invalid_json, invalid_query, invalid_storage_key400
Authunauthorized401
Creditspayment_required402
Authorizationforbidden403
Not Foundnot_found404
Conflictconflict, request_in_progress, duplicate_request409
Rate Limitrate_limit_anonymous_abuse, rate_limit_requests_exceeded, rate_limit_tokens_exceeded, rate_limit_cost_exceeded, rate_limit429
Internalinternal_error, database_error, serialization_error500
Externalexternal_service_error502
Unavailableservice_unavailable503

400 — Validation

CodeMessageNotes
validation_errorValidation error: <message>details: { "field": "<name>" }
validation_errorRequest validation faileddetails: { "errors": { "<field>": [...] } } — per-field arrays
invalid_jsonInvalid JSON in request bodydetails: { "error": "<rejection>" }
invalid_queryInvalid query parametersdetails: { "error": "<rejection>" }
bad_requestMESSAGE_REQUIREDAgent execute — no user message
bad_requestEMPTY_MESSAGEWhitespace-only message
bad_requestclient_tools_not_accepted: ...No AI node accepts client tools
bad_requesttoo_many_client_tools: <N> exceeds limit of <M>Client tool count exceeded
bad_requestclient_tool_name_collision: '<name>' ...Tool name conflicts with server tool
validation_errorinvalid_tool_name: '<name>' must match ^[a-z][a-z0-9_]{0,63}$field: "client_tools"
validation_errorpayload size <N> bytes exceeds limit of <M> bytesfield: "variables". Default 16 KiB
bad_requestMissing X-Workspace-Id header
bad_requestX-Workspace-Id must be a UUIDv7
bad_requestX-Workspace-Id contains invalid charactersOnly [A-Za-z0-9_-]
invalid_storage_keymissing namespace: <key>
invalid_storage_keyunknown namespace: <ns>Only attachments, media, thumbnails

401 — Unauthorized

CodeMessageNotes
unauthorizedMissing authorization header
unauthorizedInvalid tokenJWT verify failed
unauthorizedInvalid or expired API keywak_ or eak_ key check failed
unauthorizedInvalid credentialsLogin — wrong password
unauthorizedRefresh token has been revokedRotation/logout consumed
unauthorizedToken verification failed: <error>Firebase JWT verify failed
unauthorizedMissing webhook signature headersFal.ai webhook
unauthorizedWebhook timestamp expiredFal.ai — 5-min tolerance
unauthorizedInvalid webhook tokenRevenueCat webhook

402 — Payment Required

CodeMessageNotes
payment_requiredinsufficient_creditsCredit balance depleted. No details.

403 — Forbidden

CodeMessageNotes
forbiddenAPI key does not have agent:execute scope
forbiddenThis agent does not allow API key accessEnable API Enabled in agent settings
forbiddenAPI key does not have access to this agentAgent allowlist mismatch
forbiddenExternal auth not enabledWorkspace feature flag off
forbiddenCustomer identity requiredEphemeral key missing external_customer_id
forbiddenRole '<Role>' cannot <action>Insufficient workspace role
forbiddenRevenueCat webhook secret not configuredWorkspace setting missing

404 — Not Found

CodeMessage
not_foundResource not found: Agent not found
not_foundResource not found: Execution not found
not_foundResource not found: Workspace not found
not_foundResource not found: No checkpoint found for execution <id>
not_foundResource not found: Conversation not found
not_foundResource not found: Customer not found
not_foundResource not found: No rate limit configured for this scope

409 — Conflict

CodeMessageNotes
conflictexecution_already_finished: cannot cancel execution in <status> statedetails: { "status", "execution_id" }
conflictexecution_awaiting_client_tool: use /tool-result to fulfilUse the tool-result endpoint
conflictexecution_terminal: cannot resume execution with status <status>Start a new turn
conflicttool_call_already_fulfilled: '<id>' has already been fulfilled
conflictEmail already in use
request_in_progressA request with this Idempotency-Key is currently being processed
duplicate_requestDuplicate request: this Idempotency-Key has already been used

429 — Rate Limit

The V2 rate limiter emits four granular codes. Key off code, not message text.

CodeMessageDetails
rate_limit_anonymous_abuseSuspicious activity detected. Try again in <N> seconds.{ "reset_in_seconds": N } — no limit disclosed
rate_limit_requests_exceededRequest limit of <N> exceeded. Try again in <M> seconds.{ "limit_type": "requests", "scope_type": "...", "limit": N, "reset_in_seconds": M }
rate_limit_tokens_exceededToken quota of <N> exceeded. Resets in <M> seconds.{ "limit_type": "tokens", "scope_type": "...", "limit": N, "reset_in_seconds": M }
rate_limit_cost_exceededSpend cap reached. Resets in <N> seconds.{ "limit_type": "cost", "scope_type": "...", "reset_in_seconds": N } — limit omitted
rate_limitRate limit exceeded. Try again in 60 seconds{ "retry_after": N } — login throttle, token exchange

scope_type values: agent, customer, user, workspace.

Headers on 429:

HeaderPresent for
Retry-After: <seconds>Always
X-RateLimit-Limit: <N>requests and tokens limit types only

SSE stream rate limit (different shape, emitted mid-stream):

{
"error": "<message>",
"code": "rate_limited",
"retry_after_seconds": 30,
"error_type": "rate_limited",
"termination_reason": "failed"
}

Note: code: "rate_limited" (not rate_limit_*) is used only in SSE streams.


500 — Internal Error

CodeMessageNotes
internal_errorAn internal error occurred. Please try again later.Real cause logged only
database_errorA database error occurred. Please try again later.MVCC conflicts — retry the request
serialization_errorA serialization error occurred. Please try again later.

502 — External Service Error

CodeMessage
external_service_errorAn external service error occurred. Please try again later.

Sources: LLM provider failures, Firebase JWKS fetch, Action node HTTP calls. The real upstream error is logged but not returned to clients.


503 — Service Unavailable

CodeMessageCause
service_unavailableCredit service not configuredCredits not enabled on workspace
service_unavailableToken exchange not configuredExternal auth not enabled
service_unavailableFile storage not configuredS3 not configured on workspace

Special Cases

  1. MISSING_WORKSPACE non-standard envelopeextractors.rs can return { "code": "bad_request", "message": "MISSING_WORKSPACE" } without timestamp/trace_id. Programming error — should not reach production.

  2. WebSocket upgrades — raw status, no body401/403/503 from the WebSocket upgrade endpoint appear as connection failures in the browser with no JSON body.

  3. SSE stream errors — use the "rate_limited" code (not rate_limit_*). Always check termination_reason.

  4. database_error (500) MVCC — classified as expected internally. Retry once.