Skip to content

Errors

Updated 2026-10-29.

Every error response has a JSON body with a code and a message.

Example

curl -s https://citadel.albastov.com/v1/models -H "Authorization: Bearer hlk_not_a_key"
401
{"error": {"code": "invalid_api_key", "message": "The API key is unknown or revoked", "type": "invalid_request_error"}}

OpenAI format

LLM routes return errors in the OpenAI format. The OpenAI SDKs raise AuthenticationError, NotFoundError, RateLimitError and APIStatusError for these errors.

503
{
  "error": {
    "message": "Loading qwen3.8-27b; retry in 150 s",
    "type": "model_loading",
    "code": "model_loading",
    "model": "qwen3.8-27b",
    "state": "starting",
    "retry_after_s": 150
  }
}
FieldValue
codeError code, snake_case (except gpu-busy, llm-unavailable)
typeOpenAI error type, or the code for model errors
messageHuman-readable text
Other fieldsPer code

Branch on the HTTP status and code. The message text can change.

LLM error codes and fields: Chat completions errors.

Citadel format

All other routes, including the docs routes, return errors in the Citadel format.

404
{"ok": false, "error": "not-found", "code": "not_found", "message": "not found"}
FieldValue
okfalse
codeError code, snake_case
messageHuman-readable text
errorcode in kebab-case (legacy; use code)
detail, metaOptional context
StatusCode
400bad_request
401unauthorized
403forbidden
404not_found
429rate_limited
500internal
501not_implemented

Retries

StatusRetry
400, 401, 403, 404, 413, 415No
429 daily_limit, daily_tokensAfter 00:00 UTC
429, other codesAfter Retry-After
500Once; then report the X-Request-Id
502After 5 to 10 s
503After Retry-After
524No; stream the request

Cloudflare errors

Cloudflare returns the following errors as plain text, before the request reaches Citadel. Check Content-Type before parsing an error body as JSON.

StatusBodyCause
403error code: 1010Blocked client signature, e.g. Python urllib
502error code: 502Citadel unreachable
524error code: 524No response headers within about 100 s