Errors and retries
REST API errors
Every refusal from the REST API (/api/v1/...) has the same body:
{
"detail": {
"code": "training_slot_occupied",
"message": "One training run at a time per account"
}
}
Branch on detail.code; show detail.message. Some errors add fields, such as
field for a refused setting, or successor for a retired path. Codes are
stable within /api/v1: a new code can appear, and an existing one keeps its
meaning.
| HTTP | Default code | Meaning |
|---|---|---|
| 400 | bad_request | The request is malformed in a way the schema cannot express. |
| 401 | unauthenticated | Missing, invalid or expired credentials; the response carries WWW-Authenticate: Bearer. |
| 402 | insufficient_credits | The account cannot pay for this operation. |
| 403 | forbidden | Authenticated, but not allowed. |
| 404 | not_found | The resource does not exist for this caller. |
| 409 | conflict | The resource's current state refuses the operation (for example training_slot_occupied or project_capability_mismatch). |
| 410 | api_version_required | A retired unversioned path; detail.successor is the path to use. |
| 413 | payload_too_large | The body is over its limit. |
| 422 | validation_error | The request failed validation; detail.errors lists every field problem. |
| 429 | rate_limited | Too many requests; honor Retry-After when present. |
| 503 | unavailable | Temporarily unavailable (for example training_unavailable); retry later. |
A route may return a more specific code with the same status, for example
training_slot_occupied (409) or embedding_selection_changed (409). The
table gives the fallback for each status.
OpenAI-compatible errors
Failures raised after an OpenAI-compatible request reaches the inference
handler use this machine-readable envelope, including legacy
/v1/completions:
{
"error": {
"message": "This project is archived. Unarchive it in project settings to serve requests.",
"type": "invalid_request_error",
"code": "project_archived",
"param": null
}
}
Authentication dependencies and request-schema validation run before that handler. Those failures currently use FastAPI's top-level shape:
{
"detail": "Invalid or inactive API key"
}
For validation, detail can be an array of field errors. Clients should first
read error.code when error is present, otherwise handle detail as a
credential or schema failure. Never branch on English message text.
Stable codes
| Code | HTTP | Retry-After | Meaning |
|---|---|---|---|
model_warming | 503 | yes | The model is starting or temporarily busy. Retry after the supplied delay, a bounded number of times. |
overloaded | 503 | yes | Reserved; an overloaded model currently answers model_warming. |
ambiguous_transport | 502 | no | The request may have reached the model. Do not blindly retry. |
upstream_error | 502 | no | The model failed after accepting the request. |
model_not_supported | 400 | no | The base model was never in this deployment's catalog. |
model_deprecated | 410 | no | The base used by a request or fine-tune is retired. Retrain on the current catalog. |
model_not_found | 404 | no | A well-formed alias or training-job reference does not resolve for this caller. |
invalid_request | 400, 413, or 422 | no | Deterministic request error. For embeddings, 400 covers more than two inputs, over the model's input limit (512 tokens, or its training length up to 2,048) per input or in total, unsupported batching, or unsupported dimensions; error.param identifies input for the input limits. |
insufficient_credits | 402 | no | The account cannot pay for this request or is not entitled to the model. |
authentication_error | 401 | no | The bearer was verified but no ReOpenly account backs it. |
project_capability_mismatch | 409 | no | The project does not expose the capability required by this route. |
capacity_unavailable | 503 | yes | The embedding model cannot take the request now: it is starting, or more requests arrived at once than it can serve. Retry after Retry-After. |
artifact_not_ready | 503 | yes | The embedding model is not ready to serve yet. Retry after Retry-After. |
upstream_validation_error | 422 | no | The embedding model returned output that failed validation (malformed, non-finite, wrong size or order), so it was not returned. |
upstream_ambiguous | 502 | no | The embedding request may have reached the model; it was not retried. Do not blindly retry. |
project_archived | 404 | no | The project is reversible but read-only until an owner unarchives it. |
internal_error | 500 | no | An unexpected server failure. Contact support with the request trace if present. |
model_deprecated is permanent for that base: production retired the 0.8B,
2B, and 4B catalog entries after the 9B cutover. Retired artifacts remain
downloadable, but serving and publishing a retired-base alias are blocked.
Retry policy
Only retry a request automatically when the response explicitly carries
Retry-After. Embeddings can emit it for capacity_unavailable and
artifact_not_ready; text generation can emit it for model_warming.
Use a bounded attempt count and preserve the original request identity. The first-party v2 playground
uses at most three automatic retries after the original request, then keeps a
manual Retry action available. It never retries a mid-stream error.
Never automatically retry:
ambiguous_transport, because the model may already have served and billing may already be recorded;upstream_error, because admission already happened;insufficient_credits,model_deprecated, andproject_archived, because changing account/project state is required;- deterministic
invalid_requestfailures.
Streaming failures
Before the first SSE frame, errors use the normal HTTP status and JSON body. After the stream begins, a mid-stream failure is sent as:
data: {"error":{"message":"…","type":"api_error","code":"upstream_error","param":null}}
The server then closes the stream without sending data: [DONE]. Treat the
absence of [DONE] as incomplete output, not as a successful empty response.