Skip to main content
Every error response from api.aurous-labs.com follows the same envelope. This page covers the shape, the 5-type taxonomy, and the recommended client-side handling for each class.

The envelope

The body fields:
  • type — one of the five top-level types (see Taxonomy below). Coarse-grained; useful for branching in error-handling code.
  • code — a specific machine-readable code like max_tokens_exceeds_hard_cap. Stable across versions; safe to switch on.
  • message — a human-readable explanation. May contain the offending value to help debug.
  • doc_url — a canonical anchor link to https://docs.aurous-labs.com/errors#<code>. Each error code has its own page.
  • request_idreq_<26-char ULID> — quote this when filing a support ticket so we can find your request.
  • param (optional) — the request parameter that failed validation. Present on most invalid_request codes.
  • status (optional) — the upstream provider’s status when we map a provider error. Present on *_provider_* codes.
The HTTP status code is the canonical signal — 400 / 401 / 403 / 404 / 409 / 422 / 429 / 5xx follow REST conventions. The type is correlated but not perfectly aligned (e.g. some 422s are type: invalid_request).

Taxonomy

Errors are bucketed into 5 top-level types: A pattern-match table for fast triage:

Retry decision tree

For each error class:

invalid_request (400 / 422) — DO NOT RETRY

Retrying with the same body will get the same 400. Look at code + param + message and fix the request. Common offenders:
  • max_tokens_exceeds_hard_cap — drop max_tokens below the model’s hard cap (see aurous_metadata.hard_max_tokens on the model)
  • model_wrong_kind — you’re hitting a chat endpoint with an embedding model, or vice versa
  • embeddings_input_too_many_items — trim parts; see Embedding limits
  • embeddings_input_too_large — text + visual + video sum exceeded 128K tokens
  • embeddings_batch_not_supported — you passed input: ["a","b","c"]; see OpenAI batch incompat
  • idempotency_key_in_use — same key, different body; use a fresh key
  • response_format_too_deep / response_format_too_large — simplify your JSON schema

authentication (401 / 403) — STOP AND INVESTIGATE

Either:
  • 401 invalid_api_key — the key doesn’t authenticate. Check it’s stored correctly; check it hasn’t been rotated/deactivated; check whitespace.
  • 403 insufficient_scope — the key authenticates but doesn’t have the required scope for this endpoint. Mint a new key with appropriate scope (full for write, read for read-only).
In both cases, retrying without fixing the key will get the same 401/403. Don’t burn retries.

not_found (404) — STOP

  • model_not_found — the model slug doesn’t exist; fetch GET /v1/models to see what’s available
  • chat_cancel_target_not_found — the cmp_<id> doesn’t exist OR belongs to a different team (we treat the second as 404 for disclosure safety)
  • resource_not_found — generic 404 for any other lookup
Retrying won’t help. Either the id is wrong or the resource has been deleted.

rate_limit (429) — BACK OFF + RETRY

Two rate-limit buckets exist:
  • RPM (requests per minute)X-RateLimit-Limit / Remaining / Reset headers
  • TPM (tokens per minute)X-RateLimit-TPM-Limit / Remaining / Reset headers (chat + embedding only)
On 429, the response carries a Retry-After header (seconds). Wait that long, then retry. The OpenAI SDK’s built-in retry honors Retry-After automatically.
See Rate limits for the per-team caps and how to interpret the headers.

server_error (500 / 502 / 503) — RETRY WITH JITTER

Two sub-classes:
  • Provider-relayed (chat_provider_unavailable, chat_provider_rate_limited, embeddings_provider_unknown_error) — the upstream provider is blipping. Will usually clear within 30 seconds.
  • Platform (internal_error, generic 500) — something broke on our side. File a support ticket with the request_id; we’ll investigate.
For both, exponential backoff with jitter is the recommended retry pattern:
Idempotency keys are critical here — without them, a retry that succeeds on the server side but failed to deliver the response over the network will double-charge. Use an Idempotency-Key: <uuid> on every retry of the same logical operation. See Idempotency.

Standard headers on errors

Every error response carries the same headers as a successful response:
  • Aurous-Request-Idreq_<ulid> for support
  • Aurous-Version — the API contract version applied
  • X-RateLimit-* — rate-limit headers (even on 429 — that’s how you know the bucket state)

Sample handler (production-grade)

Where to next?