Skip to main content

Errors

The API uses standard HTTP status codes and OpenAI-compatible JSON error responses. Use the HTTP status for broad handling and error.code when you need to distinguish errors that share a status, such as the two 429 responses.

Error envelope

Celeris API errors use this shape:

{
"error": {
"message": "Invalid or missing API key.",
"type": "authentication_error",
"code": "invalid_api_key"
}
}
  • message — a human-readable description.
  • type — a broad error class, such as authentication_error or rate_limit_exceeded.
  • code — a stable, machine-readable code. Use it to distinguish errors that share an HTTP status. See 429.

Some infrastructure-level 5xx responses may not include a JSON body. Retry all 5xx responses by status rather than requiring an error.code value.

If you send an X-Client-Trace-Id header, Celeris echoes it in API responses so you can correlate failures with application logs and support cases.

StatuscodeRetry?
400Varies by validation errorAfter fixing the request
401invalid_api_keyAfter fixing credentials
402insufficient_quotaAfter adding credit
404not_foundAfter fixing the URL
413payload_too_largeAfter reducing the request body
429rate_limit_exceeded / service_busyYes; honor Retry-After
502upstream_errorYes, with backoff
503service_unavailableYes, with backoff

400 Bad Request

The request is invalid. The response body describes the validation error.

Common causes:

  • Malformed JSON, or a messages array that doesn't match the chat format.
  • Prompt plus max_tokens exceeds the model's 4,096-token context window. Requests are not silently truncated.
  • A parameter outside its valid range (e.g. negative max_tokens).

What to do: correct the request before retrying.

401 Unauthorized

Code: invalid_api_key (type authentication_error). The Authorization header is missing, malformed, or carries a key that is unknown or revoked.

{"error": {"message": "Invalid or missing API key.", "type": "authentication_error", "code": "invalid_api_key"}}

Common causes:

  • No Authorization: Bearer dg_... header, or a typo in it.
  • A revoked or rotated key still deployed somewhere.
  • A recently created key that is still within the documented activation window.

What to do: check the header and the key's status in the Console. Don't retry unchanged requests. If the key was just created or rotated, wait up to one minute before trying again.

402 Payment Required

Code: insufficient_quota (type insufficient_quota). Your workspace has no prepaid credit remaining.

{"error": {"message": "Your prepaid credit balance is exhausted. Add credit to continue.", "type": "insufficient_quota", "code": "insufficient_quota"}}

What to do: top up credits in the Console, then retry. Do not retry until credit is available. Because the balance is shared by all keys in the workspace, production systems should alert on this response.

404 Not Found

Code: not_found (type invalid_request_error). The URL does not identify an available model, usually because of a typo in the model segment of the base URL.

{"error": {"message": "No model is served at this path. Check the URL path segment.", "type": "invalid_request_error", "code": "not_found"}}

What to do: compare the URL and request-body model field with the values in Models.

413 Payload Too Large

Code: payload_too_large (type invalid_request_error). The request body exceeds the endpoint's maximum size.

{"error": {"message": "The request body exceeds the maximum allowed size for this model.", "type": "invalid_request_error", "code": "payload_too_large"}}

What to do: reduce the request body before retrying. A prompt that fits the byte limit but exceeds the model's token context window returns a 400.

429 Too Many Requests

Two codes share this status. Both are retriable and include a Retry-After header in seconds:

  • rate_limit_exceeded — the workspace exceeded its request-rate limit.
  • service_busy — the service is temporarily unable to accept more work.
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 1

{"error": {"message": "You have exceeded your workspace's request rate. Slow down and retry, or contact support for a higher sustained limit.", "type": "rate_limit_exceeded", "code": "rate_limit_exceeded"}}
{"error": {"message": "The service is busy. Please retry in a moment.", "type": "rate_limit_exceeded", "code": "service_busy"}}

Requests that return 429 are not charged.

What to do: wait at least as long as Retry-After, then retry with exponential backoff and jitter. If rate_limit_exceeded persists, reduce concurrency or contact support about a higher sustained rate. Report persistent service_busy responses to support.

502 Bad Gateway

Code: upstream_error (type api_error). The model service is temporarily unavailable.

{"error": {"message": "The model service is temporarily unavailable. Please retry with backoff.", "type": "api_error", "code": "upstream_error"}}

What to do: retry with backoff.

503 Service Unavailable

Code: service_unavailable (type api_error). The service is temporarily unavailable.

{"error": {"message": "The service is temporarily unavailable. Please retry shortly.", "type": "api_error", "code": "service_unavailable"}}

What to do: retry with backoff. If the error persists, check the Console or contact support. Retry any 5xx by status; do not require a JSON body or a specific error code.

Retries and timeouts

  • Retry 429, 502, and 503 — with exponential backoff and jitter, honoring Retry-After when present.
  • Don't retry 400, 401, 402, or 404 without changing something first.
  • Set client timeouts. Choose a timeout that matches your workload and latency objective. Treat timeouts as transient and retry with backoff.

A note for OpenAI SDK users

OpenAI SDKs expose Celeris errors as HTTP exceptions. Branch on the HTTP status, or inspect error.code when you need to distinguish the two 429 responses:

from openai import APIStatusError

try:
response = client.chat.completions.create(...)
except APIStatusError as err:
if err.status_code == 429:
... # back off and retry
elif err.status_code == 401:
... # fix credentials; do not retry
else:
raise