Skip to main content

Error reference

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 published OpenAPI schema. Switch on code first, then read details. Codes not listed in the "structured details" section below either carry no details or a free-form payload and should be treated as opaque.

error.code catalogue

HTTPerror.codeCause
400bad_requestHTTP-level precondition (e.g. Prefer: respond-async with non-JSON Accept).
401unauthorizedMissing/malformed Authorization, or key not registered. Response always carries WWW-Authenticate: Bearer … per RFC 6750 §3.1; the error= parameter is invalid_request for a malformed/missing header, invalid_token for an unrecognised key. The JSON error.code is unauthorized in both cases.
403forbiddenKey registered but disabled.
404not_foundUnknown route, unknown job, or cross-tenant access (returns 404 not 403 to prevent id enumeration).
404model_not_foundmodel field references an unknown model. error.details.available_models lists alternatives.
409conflictReserved (e.g. busy-model unload conflict).
410job_expiredAsync result no longer available (24 h TTL).
413payload_too_largeBody exceeded the 16 MiB hard cap.
413sync_too_largeReserved. Schema-typed (SyncTooLargeDetails) for future use; no partner-visible endpoint emits it today. See ./limits.md for soft per-task async-opt-in guidance.
415unsupported_formatThe task's Accept / ?format= value is not in its allowed text-format set (e.g. gff3 requested on a task that only emits bed).
422validation_failedPydantic rejection. error.details is the FastAPI errors array; error.message summarises the first issue.
422task_not_supported_by_modelModel exists but is registered for a different task. error.details.{task,supported_tasks}.
429too_many_requestsConcurrency cap, per-key rate cap, or edge per-IP cap reached. All three paths emit {error: {code: "too_many_requests", …}} and Retry-After; the application paths additionally emit RateLimit-* headers (see ./limits.md). For the edge path, error.request_id is an edge-assigned identifier (32 hex chars) rather than a UUID; it still correlates with the edge access log.
500internal_errorUnanticipated; the original exception is never returned on the wire. Quote request_id.
503model_loadingWarm-up failed or competing load in progress. Retry after ~30 s.
503service_unavailableReserved (startup/shutdown).
504(no envelope)Sync request exceeded the upstream read timeout (300 s). Body is the edge proxy's, not the unified {error: {...}} envelope — the only response on the contract that is not the unified error envelope. Retry the request with Prefer: respond-async.

Structured details shapes

error.codeerror.details shape
validation_failed{ "errors": [<FastAPI validation array>] } — each entry has {loc, msg, type} (and optional input/ctx).
task_not_supported_by_model{ "task": "<requested task>", "supported_tasks": ["<task>", ...] }
model_not_found{ "available_models": ["<model>", ...] }
sync_too_large{ "sequence_length": <int bp>, "threshold": <int bp> }

Other codes (unauthorized, forbidden, too_many_requests, payload_too_large, bad_request, not_found, conflict, job_expired, unsupported_format, internal_error, model_loading, service_unavailable) do not ship structured details; the human-readable message is the only payload.

Handling errors

Three buckets:

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