Skip to main content

Errors

Authoritative source

The per-code list and the typed error.details shapes are in the published OpenAPI schema — browse them in ReDoc or fetch /v1/openapi.json. This page covers the envelope, the discriminate-on-code rule, the handling strategy, and a few codes whose behavior the schema can't fully express.

Every non-2xx response uses the unified envelope:

{
"error": {
"code": "<machine_readable_snake_case>",
"message": "<human-readable summary>",
"request_id": "<server-assigned id>",
"details": "<optional, code-specific>"
}
}

error.code is the authoritative discriminator. Never parse error.message. The same request_id appears on the X-Request-Id response header and on every server log line for the request — quote it in support tickets.

error.details is typed per code in the OpenAPI schema (e.g. validation_failed, task_not_supported_by_model, model_not_found, sync_too_large each carry a structured payload). Switch on code first, then read details; codes without a typed shape carry only the human-readable message and should be treated as opaque.

Notable codes

Most codes are self-explanatory from the OpenAPI schema. A few have behavior worth noting:

  • 504 (no envelope): a sync request past the upstream read timeout is terminated by the edge proxy with the proxy's body, not the unified {error: {...}} envelope (see Limits). Retry with Prefer: respond-async.
  • 404 not_found on cross-account access: accessing another caller's job returns 404, not 403, to prevent id enumeration.
  • 413 sync_too_large: emitted only by the composite find-genes-and-predict-expression workflow when submitted synchronously above 50,000 bp; resubmit with Prefer: respond-async. No /v1/tasks/{task}/predict endpoint emits it. See Limits.
  • 429 too_many_requests: comes from three paths — the per-key concurrency cap, the per-key rate cap, or the edge per-IP cap. All emit Retry-After; the application paths also emit RateLimit-* headers. On the edge path, error.request_id is an edge-assigned identifier (32 hex chars) rather than a UUID, but still correlates with the edge access log. See Limits.

Handling errors

Three buckets:

  1. Retryable transient (429, 503): honor Retry-After; if absent, exponential backoff capped at ~30 s.
  2. Permanent (other 4xx): surface error.message to the user; do not retry. 422 validation_failed messages are usually deterministic and safe to echo verbatim.
  3. Server bug (5xx other than 503 and 504): capture request_id and contact us. One retry is fine; tight loops are not.

504 is the exception to bucket 3: it carries no envelope and means the sync request outran the proxy window, so retry it with Prefer: respond-async rather than treating it as a server bug (see the note above).


Back to the workflow: REST API guide · Tasks.