Skip to content

Error Handling

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"
}
}
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.

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).

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.

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.
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.
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.
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.

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.

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-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"
}
}

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"
}
}

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.

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: error
data: {"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.

The envelope above applies to:

  • POST /v1/chat/completions
  • POST /v1/responses
  • POST /v1/audio/transcriptions
  • GET /v1/models and GET /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.

You can check the current status of our API at status.compactif.ai.