Skip to content

Errors

The error format, every status code, errors in a stream, retries and debugging.

Format

{
  "error": {
    "code": 400,
    "message": "invalid chat completion request",
    "metadata": { "fields": { "messages": "messages must be a non-empty array" } }
  }
}
  • code equals the HTTP status.
  • message is in English. When a provider rejects a request (4xx), its own message is passed on without parts that name the provider or link to it; for a provider rate limit (429) or failure (5xx) the message is the router's.
  • metadata.provider_name names the region of the provider that failed: global or ru.
  • metadata.fields maps each invalid field to its problem, for 400 validation errors.

Status codes

StatusWhenRetry?
400Invalid body; unknown model (model … is not available); no route for the model and the request (no route of …); a provider rejected the requestNo: fix the request
401Invalid, disabled, expired or revoked API keyNo
402Not enough PnP, or a key or space budget is reachedAfter a top-up
403The space has no payer, lost access to it, or is deletedNo
404GET /generation: no such generation in this spaceNo
409The payer of the space changed during the requestYes, at once
413The body is over 4 MiBNo
422A provider could not process the requestNo
429A router or provider rate limitYes, with backoff
502A provider failed before the answer startedYes, with backoff
503The router could not confirm the payer's balance, its limits are unavailable, or it is overloadedYes, with backoff
504A provider did not answer in timeYes, or use streaming

Errors in a stream

After a stream has started, the status is 200 and an error arrives as an event with error and finish_reason: "error". See Streaming.

Retries

  • Retry 429, 502, 503, 504 and 409 with exponential backoff and jitter.
  • Do not retry 400, 401, 402, 403, 413, 422: the same request fails again.
  • There is no idempotency key, and a retry is a new request. An error the provider returned before the answer started is not billed; after a timeout in the middle of an answer, the part generated is billed. Check billable of the attempts in GET /api/v1/generation when in doubt.
  • Better than retrying the same model: give fallback models in models, see Models and routing.

Debugging

  • Every response has an X-Request-Id header. Mention it when you contact support.
  • A generation has an id (id of the response, X-Generation-Id of a stream). GET /api/v1/generation?id=gen-… shows its state, tokens, cost and every attempt with its status, see GET /generation.
  • The cabinet logs show the same for every call, and the request and answer when content logging is on.
Nodul Router — one API for every model