Error Handling
Error shape
Section titled “Error shape”Every error is returned as JSON with a single top-level error object. All four fields are
always present; param and code are null when they don’t apply.
{ "error": { "message": "Model 'nonexistent-model' not found; available: [carina-60b, glm-5-2]", "type": "invalid_request_error", "param": "model", "code": "model_not_found" }}Error properties
Section titled “Error properties”| Property | Description |
|---|---|
message |
Human-readable description of what went wrong. Intended for display and logs. Do not parse or match on this string — wording may change at any time without a major version bump. |
type |
Broad machine-readable category. Always one of the five values in the table below. |
param |
The request field that caused the error, in dotted/indexed notation (model, file, messages[0].role). null when the error isn’t attributable to a single field. |
code |
Stable machine-readable code for programmatic branching. null when no specific code applies. |
Branch on code when you need to handle a specific condition, and fall back to type (or the
HTTP status) otherwise. Both are stable; message is not.
Error types
Section titled “Error types”| HTTP status | type |
|---|---|
| 400, 404, and other 4xx | invalid_request_error |
| 401 | authentication_error |
| 403 | permission_error |
| 429 | rate_limit_error |
| 5xx | server_error |
402 maps to invalid_request_error — an exhausted prepaid wallet is a
request-refusal condition, not a transient overload. Distinguish it by its
code (wallet_depleted), not its type.
There is no separate type for 404 — a missing model or response is reported as
invalid_request_error with a code that identifies it (model_not_found,
previous_response_not_found).
Error codes
Section titled “Error codes”The code values below are stable. New codes may be added in a minor release, so treat an
unrecognised code as “handle by type instead” rather than as an error.
Model errors
Section titled “Model errors”code |
Status | Meaning |
|---|---|---|
model_not_found |
400 / 404 | The model doesn’t exist, or your token has no access to it. 404 on GET /v1/models/{model} and POST /v1/chat/completions; 400 on POST /v1/responses and POST /v1/audio/transcriptions. |
model_required |
400 | The request body is missing a non-empty string model field. |
audio_not_supported |
400 | The model can’t accept input_audio in POST /v1/chat/completions — or the request sent audio to /v1/responses, which takes none. Check supports_audio in GET /v1/models. |
audio_transcription_not_supported |
400 | The model can’t serve POST /v1/audio/transcriptions. Check supports_audio_transcription in GET /v1/models. |
audio_output_not_supported |
400 | The request asked for audio output (modalities includes "audio"), referenced an earlier audio response (audio.id on an assistant message), or sent audio output parameters without "audio" in modalities. No model generates audio. |
audio_too_large |
400 | An input_audio clip exceeds 50 MB decoded or 30 minutes of audio. Shorten, downsample or re-encode the clip. |
model_endpoint_not_configured |
500 | The model has no provider endpoint configured. Server-side misconfiguration — contact support. |
model_configurations_unavailable |
500 | No model configurations are loaded. Server-side — contact support. |
Request and file validation
Section titled “Request and file validation”code |
Status | Meaning |
|---|---|---|
invalid_request |
400 | The model provider rejected the request parameters. |
invalid_value |
400 | A field’s value is invalid, e.g. input_audio.data that isn’t base64 or whose format label doesn’t match its bytes. param names the offending field. |
missing_required_parameter |
400 | A parameter required by another one is missing, e.g. audio when modalities includes "audio". param names it. |
file_required |
400 | A required file was not supplied. |
empty_file |
400 | The supplied file has zero bytes. |
file_too_large |
400 | The file exceeds the maximum accepted size. The limit is stated in message. |
unsupported_file_format |
400 | The file’s content type isn’t supported. Supported types are listed in message. |
unsupported_file_extension |
400 | The filename extension isn’t supported. Supported extensions are listed in message. |
invalid_stream_value |
400 | The stream form field isn’t a recognised boolean. |
Responses API
Section titled “Responses API”code |
Status | Meaning |
|---|---|---|
previous_response_not_found |
404 | The previous_response_id doesn’t exist or isn’t accessible to your token. |
response_not_found |
404 | The requested stored response doesn’t exist or isn’t yours. |
chat_store_disabled |
400 | Response storage isn’t enabled for this deployment, so previous_response_id and response retrieval are unavailable. |
invalid_parameter_combination |
400 | Mutually exclusive parameters were supplied together. |
function_call_not_found |
400 | A function_call_output item references a call_id with no matching function call. |
function_call_output_missing_call_id |
400 | A function_call_output input item is missing its call_id. |
mcp_call_missing_name |
400 | An MCP call input item is missing its name. |
file_not_found |
400 | The file_id doesn’t resolve to a stored file. |
files_not_configured |
500 | File inputs aren’t available on this deployment. |
chat_store_misconfigured |
500 | Response storage is enabled but misconfigured. Server-side — contact support. |
chat_store_unavailable |
502 | The response store could not be reached. Retry shortly. |
file_store_unavailable |
502 | The file store could not be reached. Retry shortly. |
Rate limits and availability
Section titled “Rate limits and availability”code |
Status | Meaning |
|---|---|---|
rate_limit_exceeded |
429 | You’ve exceeded your rate limit. See Rate limits. |
wallet_depleted |
402 | Your prepaid balance is exhausted. See Wallet depletion (402). |
upstream_unavailable |
502 | The model provider is temporarily unavailable. Retry shortly. |
no_healthy_llm_provider |
503 | No healthy provider is currently serving this model. Retry shortly. |
no_llm_provider_attempted |
503 | No provider was available to attempt the request. Retry shortly. |
first_token_timeout |
503 | The model did not start responding in time, and no alternative responded either. Retry shortly. |
request_deadline_exceeded |
503 | The request’s overall time budget expired before any content was produced. Retry shortly. |
no_content |
503 | The stream ended before any content was produced. Retry shortly. |
internal_error |
500 | Unexpected server-side failure. Retry; if it persists, contact support. |
Authentication errors (401)
Section titled “Authentication errors (401)”Returned when no Authorization: Bearer header is present, the token is malformed, or the token
isn’t associated with a valid user.
{ "error": { "message": "Missing authentication token", "type": "authentication_error", "param": null, "code": null }}See the Authentication guide for how to obtain and use a token.
Request validation errors (400)
Section titled “Request validation errors (400)”Malformed request bodies return 400 (not 422). The response reports the first offending field in
param, using dotted and indexed notation so you can locate it in the JSON you sent. When more
than one field failed, message ends with a count of the remainder.
{ "error": { "message": "Missing required parameter: 'messages'. (and 2 more validation errors)", "type": "invalid_request_error", "param": "messages", "code": null }}A body that isn’t valid JSON at all has no attributable field, so param is null:
{ "error": { "message": "Invalid JSON in request body: Expecting ',' delimiter.", "type": "invalid_request_error", "param": null, "code": null }}Rate limits (429)
Section titled “Rate limits (429)”Rate-limited responses carry a Retry-After header with the number of seconds to wait, and
code is rate_limit_exceeded. Honour Retry-After rather than retrying immediately.
{ "error": { "message": "Rate limit exceeded. Please retry in 12 seconds.", "type": "rate_limit_error", "param": null, "code": "rate_limit_exceeded" }}Wallet depletion (402)
Section titled “Wallet depletion (402)”Accounts on prepaid billing are checked before the request is served. When the wallet is
exhausted, the API returns 402 with code wallet_depleted (note its
type of invalid_request_error, since topping up — not retrying — is the remedy):
{ "error": { "message": "Your prepaid balance is exhausted (0.00 USD remaining). Top up your wallet to continue.", "type": "invalid_request_error", "param": null, "code": "wallet_depleted" }}Server errors (5xx)
Section titled “Server errors (5xx)”message for a 5xx is deliberately generic — details are recorded server-side, not returned to
callers. Use code to distinguish the cases.
{ "error": { "message": "Unexpected server error! Please retry shortly.", "type": "server_error", "param": null, "code": "internal_error" }}502 and 503 indicate a transient upstream or capacity problem rather than a bug in your request.
Retry these with exponential backoff. A 500 with internal_error is worth retrying once; if it
persists, contact support.
Errors while streaming
Section titled “Errors while streaming”When stream: true, the HTTP status is sent before the failure can occur, so errors arrive as an
SSE event instead. The API emits an event: error whose data: line is the same envelope you’d
receive from a non-streaming call, followed by the data: [DONE] sentinel:
event: errordata: {"error":{"message":"Unexpected server error! Please retry shortly.","type":"server_error","param":null,"code":"internal_error"}}
data: [DONE]Parse every data: payload as JSON except [DONE]. Note that content emitted before the error
is still valid — a stream can fail partway through, so treat a run that ends with an error
event as incomplete rather than discarding what you already received.
Endpoint coverage
Section titled “Endpoint coverage”The envelope above applies to:
POST /v1/chat/completionsPOST /v1/responsesPOST /v1/audio/transcriptionsGET /v1/modelsandGET /v1/models/{model}
The legacy POST /v1/completions endpoint still returns errors in the older
{"detail": "..."} form and is unaffected by the fields described on this page. Prefer
POST /v1/chat/completions for new integrations.
API status
Section titled “API status”You can check the current status of our API at status.compactif.ai.