Errors and request identifiers

When LYRouter rejects a call, it returns a 4xx or 5xx status code. On OpenAI-compatible endpoints the error body is {"error": {"message", "type", "code"}}; on /v1/messages it is converted to the Anthropic format; a few responses are an HTML page or a single line of plain text. Look up the status code and the exact error.message in the quick reference on this page to tell whether the problem lies in the request itself, in the account and configuration, or with the platform or the upstream provider, and what to do about it. The gateway does not return a request ID in response headers. To pin down a specific call, open the request's detail in Log analysis and copy the Request ID at the top.

Error response format

OpenAI-compatible format

Apart from /v1/messages, every endpoint (Chat Completions, Responses, Embeddings, images, video and others) returns this error body by default:

{
  "error": {
    "message": "insufficient credit balance",
    "type": "insufficient_quota",
    "code": "insufficient_credit_balance"
  }
}
Field Description
message The error message, mostly in English and occasionally in Chinese. The messages listed on this page match what the gateway returns word for word; <...> marks the parts that are replaced
type The error category, such as invalid_request_error, permission_error, access_denied, guardrail_blocked, insufficient_quota, rate_limit_error, billing_unavailable, service_unavailable or api_error
code A machine-readable identifier. Only some errors have one; when there is none, the whole field is omitted. The same message can come with several code values (for example insufficient credit balance), so branch your program on code first
Additional fields Carried by only a few errors: limit, used, reset_at and others on quota 429s; retry_after and blocked_until on circuit-breaker 429s; upstream_status, generated_by and others on error bodies filled in for an empty upstream response

Anthropic format (/v1/messages)

When you call through /v1/messages, both the gateway's own errors and upstream errors are converted to the Anthropic format, with message unchanged:

{
  "type": "error",
  "error": { "type": "authentication_error", "message": "invalid api key" }
}
HTTP status error.type
400, 402, 422 invalid_request_error
401 authentication_error
403 permission_error
404 not_found_error
413 request_too_large
429 rate_limit_error
503, 529 overloaded_error
500, 502, 504 and other 5xx api_error

After conversion, error.code and the additional fields (such as limit and retry_after) are dropped; response headers are kept as usual. The error messages on this page apply to /v1/messages too. When you need to tell specific causes apart, go by the status code plus message, or look up the request in the logs.

The 404 → not_found_error mapping above does not apply to a 404 for a path or HTTP method that does not exist: calling /v1/messages with GET, for example, returns 404 {"error_msg":"404 Route Not Found"}, which is not converted to the Anthropic format.

Responses that are not JSON error bodies

Situation Status Response body
Connecting to the upstream failed, or waiting for the upstream timed out 500, 504 HTML error page
Wrong Content-Type, malformed multipart request, or a required native passthrough cannot be satisfied (converted to the Anthropic format on /v1/messages; see above) 400 One line of plain text, such as unsupported content-type: text/plain, only application/json is supported
The workspace has a default model set, and the request body is not valid JSON or is empty 400 {"message": "..."}, with no outer error
The path or HTTP method does not exist, such as /v1/v1/chat/completions, or calling /v1/chat/completions with GET 404 {"error_msg": "404 Route Not Found"}

For a plain-text 400 returned by the gateway, the Content-Type response header is currently still application/json, so parsing it directly as JSON fails, and some SDKs report an error such as "unable to parse the response". A safe approach is to check the status code first, then check whether the body is JSON (try to parse it); if it parses, read error.message, message and error_msg in that order; if none is present, log the first few hundred characters of the raw response:

# -i also prints the status line and response headers (such as Retry-After and x-aigw-quota-*)
curl -sS -i https://api.lyrouter.com/v1/chat/completions \
  -H "Authorization: Bearer $LYROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"MODEL_ID","messages":[{"role":"user","content":"Hello"}]}'

Quick reference

In the Who handles it column, "administrator" means the current Account Owner or a workspace Admin, and "Contact support" means the platform needs to act.

Status Error message (error.message) error.code Cause Who handles it
400 you must provide a model parameter missing_model No model in the request, and the workspace has no default model Caller
400 invalid type for 'model': expected a string invalid_model model is not a string Caller
400 request body must be a JSON object invalid_json The request body is not a valid JSON object; some versions return missing_model Caller
400 could not get parse JSON request body: <parse error> — (no outer error) Same as above, when the workspace has a default model set Caller
400 unsupported content-type: <type>, only application/json is supported — (plain text) Content-Type is not JSON Caller
400 multipart body has no non-empty `model` field and others — (plain text) The multipart body is missing a field or has an invalid value Caller
400 This model does not support the <api> API and others unsupported_model_api and others The model does not support this endpoint, operation or input type Caller switches models
400 unsupported parameters for this model: <parameter> unsupported_parameters In strict mode, the request has parameters the model does not support Caller
400 The specific parameter's validation message invalid_parameter Parameters or multipart content of image, video and similar endpoints are invalid Caller
400 native passthrough was required by `x-gateway-passthrough: require` ... — (Anthropic format on /v1/messages, plain text on other endpoints) Native passthrough was required, but this request cannot be passed through Caller
401 missing credentials — No API key Caller
401 invalid authorization scheme, expected 'Bearer' — The Authorization header is malformed Caller
401 invalid api key — The key does not exist, or was deleted, disabled or has expired Caller / administrator
401 api key verification unavailable — The platform's key verification service is temporarily unavailable Retry later
402 insufficient credit balance insufficient_credit_balance and others The account balance is insufficient Account Owner tops up
402 subscription expired; renew to continue — The subscription has expired Account Owner renews
403 api key expired — The key is past its expiry time Create a new key
403 your IP address is not allowed — The source IP is not on the key's allowlist Caller / key creator
403 ip access control misconfigured — The key's IP allowlist is invalid Key creator
403 api key workspace is unavailable — The workspace configuration temporarily cannot be read Retry later
403 Model is not available in the model plaza model_not_available The workspace has not enabled this model Administrator / switch models
403 Request blocked by guardrail policy guardrail_* Guardrails blocked the request Caller / administrator
403 Response blocked by guardrail policy guardrail_sensitive Guardrails blocked the model's answer Caller / administrator
403 Subject is blocked by an active security ban guardrail_subject_banned Guardrails have banned the key Administrator
403 该 API Key 已被永久封禁,无法恢复,请删除后创建新的 API Key。 (This API key has been permanently banned and cannot be restored; delete it and create a new API key.) api_key_permanently_banned The key tripped the error-rate circuit breaker for the 5th time Fix the program, then create a new key
404 404 Route Not Found (in the error_msg field) — Wrong path or HTTP method Caller
404 / 409 video task not found, video is not ready yet and others not_found and others The video task does not exist, has not finished or cannot be canceled Caller
429 rate limit exceeded on <subject> <metric>/<window> — A quota or budget is used up Wait for the reset / administrator raises the limit
429 API Key 因最近 60 秒错误率过高已临时熔断,请在 N 秒后重试。 (The API key has been temporarily circuit-broken because its error rate over the last 60 seconds was too high; retry in N seconds.) api_key_circuit_open The key was temporarily circuit-broken for a high error rate Fix the cause, then wait as long as Retry-After says
429 all upstream credentials for this model are rate limited upstream_quota_exhausted Every upstream credential for this model has reached its limit Retry later / switch models
429 upstream concurrency full upstream_concurrency_full Upstream concurrency for async tasks is full Retry later
500 HTML error page — Connecting to the upstream failed, or reading the response failed Retry later
500 sync spec needs the upstream model name for the path and others model_unresolved and others A platform-side channel configuration problem Contact support
503 all routed candidates exhausted no_route_candidate No model or channel can serve the request Caller / administrator
503 No configured credential can serve this model no_route_candidate The model has no usable credential Administrator
503 Workspace model projection is unavailable workspace_model_projection_unavailable The workspace's model configuration temporarily cannot be read Retry later
503 billing balance is temporarily unavailable billing_maintenance and others The account balance temporarily cannot be confirmed Platform (some cases recover with a later retry; contact support if it persists)
503 Platform supplier cost snapshot is unavailable supplier_cost_snapshot_not_ready The channel price for this model is not ready Switch models and contact support
504 HTML error page — Waiting for the upstream's response timed out Retry later
The upstream's status code The upstream's error message Defined by the upstream, or upstream_* The upstream provider rejected the request Depends on the message

400: request format or parameters

The gateway returns every 400 in this section before sending the request to the upstream.

Model field and request body

Error message error.code Meaning and fix
you must provide a model parameter missing_model model is missing, "" or null (the same applies to an empty request body), and the workspace has no default model set in Smart routing. Put a model ID in the request; you can list them with GET /v1/models
invalid type for 'model': expected a string invalid_model model was written as a number, an object or the like. A default model does not take its place even when one is set; change it to a model ID string
request body must be a JSON object invalid_json The request body is valid JSON, such as a string or a number, but not an object; when the request body is not valid JSON, the message is could not get parse JSON request body: <parse error>, also with error.code invalid_json. Some versions return you must provide a model parameter (missing_model) for both kinds of body; a JSON array as the request body also returns missing_model. Check quotes, commas and escaping, and whether the body actually went into -d / json=
could not get parse JSON request body: <parse error> (sic) — When the workspace has a default model set, invalid JSON returns this message with the response body {"message": "..."}; an empty request body returns could not get body: request body is empty. Fix as above

When a default model is set, a chat request without model is answered by the default model instead, and you do not get missing_model. Setting the default model is covered in Channels and routing.

Content-Type and multipart (plain-text responses)

Error message Meaning and fix
unsupported content-type: <type>, only application/json is supported The request's Content-Type header is not application/json. For JSON endpoints, set Content-Type: application/json; requests without this header are treated as JSON. /v1/images/edits and /v1/videos accept both JSON and multipart/form-data
multipart body has no non-empty `model` field The multipart body has no non-empty model form field. When the workspace has no default model, you must provide a model parameter is returned first
request body is empty The multipart request body is empty
<field> must be `true` or `false` in multipart form data In /v1/videos multipart requests, watermark and generate_audio accept only the literals true or false; 1, yes and True are all rejected
input_reference must be a URL; uploading a file is not supported by this gateway (pass a publicly reachable https:// URL instead) In /v1/videos multipart requests, pass input_reference (the reference video) as a publicly reachable https:// URL; uploading a file is not supported

Model does not support the endpoint or input

type is invalid_request_error; tell them apart by error.code:

error.code Error message Meaning
unsupported_model_api This model does not support the <api> API The model does not support this kind of endpoint; <api> is one of chat_completions, responses, embeddings, rerank, images and videos. For example, calling the image generation endpoint with a chat model
unsupported_model_operation This model does not support the <operation> operation The model supports this kind of endpoint but not this operation within it, such as images_edits or videos_regenerations
unsupported_model_input This model accepts text input only Images, audio or files were sent to a model that accepts only text

Fix: check the endpoints and input types a model supports in Model marketplace, and switch to a model that supports them; see Capabilities and compatibility.

Unsupported or invalid parameters

unsupported parameters for this model: <parameter> (unsupported_parameters): the request carries X-Gateway-Strict-Parameters: true and contains parameters the selected model does not support. Without this request header, the gateway drops those parameters, makes the call as usual and lists their names in the X-Gateway-Unsupported-Parameters response header. Both headers currently cover only image and video endpoints; parameters that chat endpoints drop during cross-protocol conversion (such as response_format, seed and n) neither trigger this error nor appear in this response header; see Gateway headers and extensions. Fix: remove the parameters listed in the error, or switch to a model that supports them.

invalid_parameter: error.message states directly which parameter is wrong and how. Common ones:

Error message Meaning
seconds must be a positive whole number of seconds The video duration must be a positive whole number of seconds
watermark must be a boolean, generate_audio must be a boolean In JSON requests, these two fields must be booleans
size implies an aspect ratio this model does not support: <value> The model does not support the aspect ratio implied by size
cannot read the multipart body, or a specific cause such as truncated multipart body: no closing delimiter or inline file parts exceed the limit of 31457280 bytes A model that needs format conversion cannot read the multipart request body: the body was truncated, the files total more than 30 MB, and so on
cannot rewrite the multipart model field: <reason> The gateway could not replace the model field in the multipart body with the upstream model name, and the request was not sent. Make sure model is a plain text field; if it persists, contact support

Value ranges for each parameter are in Multimodal capabilities.

Native passthrough not available

Message: native passthrough was required by `x-gateway-passthrough: require` but is not available for this request (<reason>)

A request with x-gateway-passthrough: require means "the request body must be sent as is to an Anthropic-protocol upstream, with no conversion". When the gateway cannot do that, it rejects the request outright instead of quietly converting it; falling back to a channel that does not use the Anthropic protocol also ends with this error. On /v1/messages this error is returned in the Anthropic format, with message identical to the message above: {"type":"error","error":{"type":"invalid_request_error","message":"native passthrough …"}}; on other endpoints it is a single line of plain text. The parentheses give the reason for the refusal:

Reason Meaning
client_protocol The call was not made through /v1/messages
route_disabled Request-side native passthrough is not enabled on the endpoint
wire_protocol The selected channel is not an Anthropic-protocol upstream
endpoint_type Not a chat endpoint
channel_disabled Native passthrough is turned off for this channel
preset_injection The virtual model used rewrites the request body (appends a system prompt, sets or locks parameters, cache strategy)
shape_oai The request body is not in the Anthropic format
decision_error The gateway's decision process failed

/v1/messages currently does not have request-side native passthrough enabled, so requests carrying this header are rejected with route_disabled. Remove the header (or change it to prefer) and the request goes through the normal protocol conversion path; see Anthropic Messages.

401: authentication failed

A 401 request cannot be attributed to any workspace and does not appear in the logs. Detailed troubleshooting for each cause is in 401 / 403: authentication and access.

Error message Meaning and fix
missing credentials The request carries no API key. Add Authorization: Bearer <API Key>; Anthropic-style clients can also use x-api-key: <API Key>. For tools configured through environment variables, open a new terminal after changing them
invalid authorization scheme, expected 'Bearer' The Authorization header is not in the Bearer <API Key> format. Bearer is case-sensitive, so bearer sk-..., the bare key and Basic ... are all rejected; Bearer with no key after it also returns this message. When a request carries both Authorization and x-api-key, only Authorization is read
invalid api key The gateway cannot find this key: it was copied incompletely or with spaces or line breaks; the key was deleted, disabled or has expired; its workspace or creator has been deactivated; or the key was just created and has not reached the gateway yet (usually a few seconds). Permanently banned keys are the exception: they keep returning 403 api_key_permanently_banned even after deletion. Copy the full key again; if the plaintext is lost, delete the key and create a new one; see Workspaces and API keys
api key verification unavailable The platform's key verification service is temporarily unavailable; this has nothing to do with whether the key is correct. Retry later; if it persists, check Service status

402: insufficient balance or expired subscription

Error message error.code Meaning and fix
insufficient credit balance insufficient_credit_balance The account's Credits balance is used up; or, when you use BYOK and a platform service fee applies, the balance is not enough to pay the service fee. The Account Owner tops up in Subscription & Credits
insufficient credit balance balance_missing The account has no balance record yet, usually because it has never been topped up. Topping up fixes it; if it still appears after a top-up, contact support
insufficient credit balance billing_entity_missing The gateway cannot find the billing account for this key. This is a platform-side data problem; contact support
subscription expired; renew to continue — The account's subscription has expired and its grace period is over, so calls from every workspace under the account are rejected. Renewing restores them; accounts without a subscription never get this error

type is insufficient_quota. The balance check happens before the call: as long as the balance is above 0, a call can start, and one call can push the balance below zero; only the calls after that are rejected. When the balance is insufficient, the gateway does not switch to another channel or billing method. Billing rules are in Billing and Credits.

403: access denied

API key and source

Error message error.code Meaning and fix
api key expired — The key is past its expiry time; the gateway checks this on every request. Create a new key to replace it; some time after expiry, the same key returns 401 invalid api key instead
your IP address is not allowed — The key has an IP allowlist, and the request's source IP is not on it (type is permission_error). The gateway checks the egress IP the request arrives from; when you call from a corporate network, through a proxy or from a cloud server, that IP may differ from the one your machine shows
ip access control misconfigured — The key's IP allowlist is empty or contains an invalid IP / CIDR, so the gateway rejects every request. The key's creator or the Account Owner fixes the allowlist
api key workspace is unavailable — The key is valid, but the gateway temporarily cannot read its workspace's configuration. This is a temporary platform-side problem; retry later
该 API Key 已被永久封禁,无法恢复,请删除后创建新的 API Key。 (This API key has been permanently banned and cannot be restored; delete it and create a new API key.) api_key_permanently_banned The key tripped the error-rate circuit breaker for the 5th time and is permanently banned; the ban cannot be lifted, and the key keeps returning the same 403 even after you delete it. Right after the ban, the message is 该 API Key 因多次高错误率请求已被永久封禁,无法恢复,请删除后创建新的 API Key。 (This API key has been permanently banned after repeated high-error-rate requests and cannot be restored; delete it and create a new API key.); once the ban has synced to the gateway, it becomes the message in this row. Fix the program that keeps failing before you create a new key, or the new key will be circuit-broken too

Permanent-ban responses carry the response header X-RateLimit-Reason: api_key_permanently_banned, and the rejected requests are not written to the logs.

Model not enabled

Model is not available in the model plaza (model_not_available, type is access_denied): in the Model marketplace of the key's workspace, every provider of this model is not enabled.

  • An administrator enables the model in Model marketplace, or the caller switches to an enabled model.
  • Using @vmodel/<name> or lyrouter/auto on image or video endpoints also returns this error: those endpoints accept only a concrete model ID.
  • When the workspace has a default model set, a chat request for a model that is not enabled is usually answered by the default model instead; you can confirm this in Model (actual) in the logs. See Unavailable models.

Guardrails

Request blocked by guardrail policy (type is guardrail_blocked): the request matched a blocking policy in the workspace's guardrails and was not sent to the model. The message does not include the policy name or the matched content; use error.code to tell the policy type:

error.code Policy matched
guardrail_client Client access: restricts calls by source IP, tool name or User-Agent
guardrail_context Intent security: the request's intent was judged risky
guardrail_sensitive Sensitive data: the request contains personal information, credentials or sensitive keywords
guardrail_injection Prompt injection: the request looks like a prompt injection
guardrail_model Model access: the chosen model is not in the allowed range; for virtual models, the model actually selected is checked
  • Response blocked by guardrail policy (guardrail_sensitive): the answer to a non-streaming request matched a sensitive-data policy. The upstream had already generated the answer, so the call is billed as usual. A streaming request that has already started output is not interrupted; the matched content is masked in the output.
  • Subject is blocked by an active security ban (guardrail_subject_banned): an intent security policy has its action set to ban, so the key that triggered it is banned, and every request is refused during the ban. The ban lifts at the automatic unban time set in the policy, or earlier when an administrator lifts it in Security events.

Retrying the same request gives the same result. The caller can change the request content or switch to an allowed model; administrators check match details in Security events and adjust policies in Guardrails; see Guardrails and semantic auditing.

404 / 409: path or resource not found

Status Error message error.code Meaning and fix
404 404 Route Not Found (response body {"error_msg": ...}) — The gateway has no such path, or the path does not accept this HTTP method. A common cause is a Base URL with an extra or missing /v1 (the OpenAI SDK's base_url should be https://api.lyrouter.com/v1, and the Anthropic SDK's is the root address); see Base URLs and authentication. These requests do not appear in the logs
404 video task not found not_found The video task ID does not exist, has expired or belongs to another workspace
409 video is not ready yet not_ready The task has not completed successfully yet, so the video cannot be downloaded. Keep polling the task status
409 cancelling an in-flight video task is not supported: ... cancel_not_supported A task in progress cannot be canceled (the upstream offers no cancel endpoint). You can still delete it after it ends

previous_response_id in POST /v1/responses is validated by the upstream provider, and an invalid one returns the upstream's error; see Responses. When a video task itself fails, the query endpoint returns HTTP 200, with the task object's status set to failed and error.code set to deadline_exceeded (timed out; the query endpoint may not show it at present, see Asynchronous tasks), canceled (canceled) or the error code given by the upstream (upstream_error by default), sometimes with the upstream's request ID in error.provider_request_id; see Asynchronous tasks.

429: rate limits, circuit breaking and upstream limits

Error message error.code Meaning and fix
rate limit exceeded on <subject> <metric>/<window> — The key's budget or a guardrail quota policy has reached its limit, such as rate limit exceeded on apikey total_tokens/day. The error body carries limit, used and reset_at (quota policies also carry policy_code and policy_name). Call again after reset_at, or ask an administrator to raise the limit
API Key 因最近 60 秒错误率过高已临时熔断,请在 N 秒后重试。 (The API key has been temporarily circuit-broken because its error rate over the last 60 seconds was too high; retry in N seconds.) api_key_circuit_open This key had at least 100 requests in the last 60 seconds and more than 90% of them failed, so it was temporarily circuit-broken. The Retry-After response header gives the number of seconds to wait, and retry_after and blocked_until (UTC) in the error body match it. Fix the cause of the failures first, then wait
all upstream credentials for this model are rate limited upstream_quota_exhausted Every upstream channel or credential that can serve this model has reached its own limit; the error body carries metric and window. Retry later or switch to another model; if the model goes only through BYOK, ask an administrator to check the credentials' limits
upstream concurrency full upstream_concurrency_full When an async task was submitted (such as POST /v1/videos), the upstream account's concurrent tasks were full, and the request was not sent. Retry later
  • Quota fields: <subject> is apikey, member, dept or ws; <metric> is requests, total_tokens, prompt_tokens, completion_tokens or credits; <window> is minute, minutes, day, month or total (cumulative, never resets). Windows are aligned to Beijing time, and usage is counted only after a request completes.
  • Response headers: when quotas are configured, responses to calls that go through gateway routing and the quota check (chat, embeddings and the like; both successful responses and quota 429s) carry x-aigw-quota-<metric>-limit / -remaining / -reset, where the metric is credits, tokens, requests, input-tokens or output-tokens; /v1/messages also carries anthropic-ratelimit-*, but credits have no matching header, so when only Credits quotas are configured the gateway does not generate anthropic-ratelimit-*.
  • Retry-After: set only by the circuit breaker (api_key_circuit_open), together with X-RateLimit-Reason: api_key_circuit_open and X-RateLimit-Reset (Unix seconds); quota 429s do not carry it. The upstream's own Retry-After is forwarded only on /v1/messages.
  • Circuit-breaker steps: 30 seconds the 1st time, 2 minutes the 2nd, 10 minutes the 3rd, 12 hours the 4th, and a permanent ban the 5th; trips accumulate over the key's whole lifetime. 402, 403 and 429 responses returned by the gateway also count as failures; circuit-broken requests are not written to the logs.

Full details are in 429: rate limits and quotas and Budgets, quotas and rate limits.

500 / 504: upstream connection failed or timed out

Status Response body Meaning
504 HTML error page Waiting for the upstream's response timed out, or connecting to the upstream timed out
500 HTML error page Connecting to the upstream failed (for example, the connection was refused or the TLS handshake failed), or reading the upstream's response failed
  • The gateway's read timeout for the upstream is 6 minutes. For streaming requests it is measured between two consecutive pieces of output, so the request does not time out as long as output keeps coming.
  • Before returning, the gateway has already tried other channels under the rules in Retries and fallback, and returns only after every candidate has failed. Once a streaming request has started output, the gateway no longer switches channels; see "Error events during streaming" below.
  • Fix: retry with capped exponential backoff; use stream: true when generating very long content; check the upstream time in Latency breakdown in the logs. See Timeouts and interrupted streams.

Configuration 500s (JSON error body)

The following 500s carry a JSON error body (type is api_error). They mean a platform-side problem with the channel or format-conversion configuration that has nothing to do with the request content, so retrying usually does not help. Note the Request ID and contact support, and switch to another model:

error.code Error message
model_unresolved sync spec needs the upstream model name for the path
spec_error unusable sync body shape: <reason>, unusable async submit spec: <reason>
unsupported_configuration remove_model is not supported on multipart endpoints
encode_failed failed to encode request body: <reason>

503: no available channel, or billing or configuration temporarily unavailable

Error message error.code Meaning and fix
all routed candidates exhausted no_route_candidate No model or channel can serve this request. Common causes are a misspelled @vmodel/<name>, a virtual model that does not exist or is disabled, or a model with no usable channel. Check the model field; if the name is correct, ask an administrator to check Model marketplace and BYOK
No configured credential can serve this model no_route_candidate The model's channels have no usable credential in this workspace: the platform channel is not enabled, or none of the BYOK credentials are usable; see BYOK
Workspace model projection is unavailable workspace_model_projection_unavailable The gateway temporarily cannot read the workspace's model configuration. This is a platform-side problem; retry later
Platform supplier cost snapshot is unavailable, BYOK supplier cost snapshot is unavailable supplier_cost_snapshot_not_ready The channels that can serve this model do not have prices configured yet, so the gateway cannot bill the call. The gateway tries other channels first and returns this only when none of them is usable. Switch to another model, and tell support the model ID
billing balance is temporarily unavailable See the table below The gateway temporarily cannot confirm the account balance, and rejects the call to avoid charging incorrectly. This is not an insufficient balance

billing balance is temporarily unavailable has type billing_unavailable; use error.code to tell whether it can recover on its own:

error.code Meaning Does retrying help
billing_maintenance The account's billing is being reconciled or under maintenance, and every call under the account is rejected No; contact support
billing_store_error, billing_store_protocol_error, byok_release_failed A temporary fault in the platform billing service It may recover later
invalid_balance, byok_billing_config_missing, byok_reservation_terminal Platform-side billing data or configuration is abnormal No; contact support

Official SDKs such as OpenAI's and Anthropic's retry 503 automatically by default, but no_route_candidate, billing_maintenance and supplier_cost_snapshot_not_ready do not recover unless the request or configuration changes.

Errors returned by the upstream provider

The gateway forwards the error status code and response body returned by the upstream provider to you as is, and the source in the Status explanation column of the logs shows Upstream.

  • Channels are tried first: when the upstream returns an error or the connection fails, the gateway retries on the same model's other channels according to the workspace's routing strategy; when all of them fail, you receive the upstream error of the last attempt. When a default model is set, a chat request may also be answered by the default model instead; see Retries and fallback.
  • Upstream 401 / 403: usually means the upstream rejected the credential. With BYOK, confirm with the provider that the API key is valid and has enough quota, then test the connection again in BYOK.
  • /v1/messages: upstream errors are converted to the Anthropic format as well.

Upstream returns an empty response body

When the upstream returns only an error status code with no response body, the gateway fills in an error body and marks it with generated_by: "ai-gateway" as generated by the gateway:

{
  "error": {
    "message": "upstream <provider> returned HTTP 429 for POST <path> with an empty response body",
    "type": "rate_limit_error",
    "code": "upstream_rate_limited",
    "upstream_status": 429,
    "generated_by": "ai-gateway"
  }
}
Upstream status error.code
400 upstream_invalid_request
401 upstream_unauthorized
403 upstream_forbidden
404 upstream_not_found
408 upstream_timeout
413 upstream_payload_too_large
429 upstream_rate_limited
Other 4xx and 5xx upstream_error

When the upstream includes its own request ID in the response headers, the error body also has an upstream_request_id; use it when you report the issue to the provider.

Upstream declares an error in a successful response

A few upstreams return HTTP 2xx but declare a failure in the response body, mostly for image and video generation. The gateway rewrites this into an error response: the status code comes from the error the upstream declared, error.code is upstream_rejected (the upstream rejected the request) or upstream_no_artifact (the upstream produced no image or video; carries upstream_finish_reason), and upstream_status is the upstream's original 2xx status code. These errors are not retried on other channels; adjust the request content according to error.message.

Error events during streaming

All the gateway rejections listed above happen before output starts, so a stream: true request also receives an ordinary error response with the matching status code, not an SSE event.

After streaming output has started (the status code is already 200), if the upstream breaks off or times out, the gateway no longer switches channels. Instead, it appends an error event at the end of the stream and then closes the connection:

OpenAI-compatible endpoints (Chat Completions, Responses and others):

data: {"error": {"message": "upstream timed out after the response had started", "type": "api_error", "code": "stream_interrupted"}}

Anthropic Messages (/v1/messages):

event: error
data: {"type": "error", "error": {"type": "api_error", "message": "upstream timed out after the response had started"}}
  • On a timeout, message is upstream timed out after the response had started; on a connection or read failure, it is upstream failed after the response had started.
  • Error events that the upstream itself sends in the stream (such as Anthropic's overloaded_error) are passed on to you in the protocol you called. The official OpenAI and Anthropic SDKs raise an API error when they receive either kind of error event.
  • After an error event, no end marker follows (data: [DONE], message_stop, response.completed). Treat "no end marker received" as a failed call, and do not treat the partial output you received as a complete result.

Event structures for each protocol are in Streaming; advice on retries and deduplication is in Timeouts and interrupted streams.

Which errors can be retried

Handling Errors
Retry with capped exponential backoff 500, 504 (HTML); 502 failed to reach upstream; 401 api key verification unavailable; 403 api key workspace is unavailable; 429 upstream_quota_exhausted, upstream_concurrency_full; 503 workspace_model_projection_unavailable, the billing_store_error group; streaming stream_interrupted
Wait for the specified time 429 api_key_circuit_open: wait Retry-After seconds; quota 429: wait until after reset_at
Call again after changing the request or configuration All 400s, 401 missing credentials / invalid authorization scheme / invalid api key, 402, most 403s, 404, 409; 503 no_route_candidate, supplier_cost_snapshot_not_ready, billing_maintenance; configuration 500s

Never retry a 4xx automatically without a delay: 402, 403 and 429 responses returned by the gateway all count toward the error-rate circuit breaker, so a program that keeps failing soon gets its key circuit-broken, and the 5th trip is a permanent ban.

Request identifiers

The gateway does not return a request ID

LYRouter does not return a request ID in response headers. The id in the response body (such as chatcmpl-..., msg_... or resp_...) is the ID of the protocol object, and you cannot search the logs by it. To pin down a call, record the call time, endpoint path, model and API key name on the client, then find the request in the logs.

Get the Request ID from the log detail

  1. Open Log analysis in the workspace's left menu. Logs are searchable within a few seconds after a call ends.
  2. Filter by Time, API Key, Model, Status and other conditions. Time in the list is when the request finished.
  3. Click the row to open Log detail; the value after Request ID at the top identifies this request. Select it and copy it.

You can paste the Request ID into the log search box to find this log again. Account Members see only logs produced by API keys they created. These requests cannot be found in the logs: 401s, 404s for a path that does not exist, requests rejected by the error-rate circuit breaker (429 api_key_circuit_open) or by a permanent ban (403 api_key_permanently_banned), and GET /v1/models. For these, provide the call time, endpoint path and full error message. Full use of the logs is covered in Troubleshooting with logs.

Other identifiers in the logs

Identifier Where to find it Use
Request ID Top of the log detail Uniquely identifies one request; provide it when you contact support
Session ID The tag in the list's Session column (turn it on under Columns), shown on hover; filter by Session ID under Add filter See every request of one conversation. Clients can declare a session with the x-session-id request header
Task ID The id returned by POST /v1/videos (starts with aigwt_); switch an async task's log detail to Whole task Query task status and artifacts, and troubleshoot async tasks
Upstream request ID Response headers of ③ Upstream response under Raw packets in the log detail (header names differ by provider, such as x-request-id); upstream_request_id in error bodies filled in for an empty upstream response; error.provider_request_id of a failed video task Report issues to the upstream provider; with BYOK, contact your own provider

What to include when reporting a problem

Information Notes
Request ID Include it when you can find the request in the logs
Call time To the minute, with the time zone
Endpoint and model Method and path (such as POST /v1/chat/completions), the model in the request, and whether it was streaming
Full error The HTTP status code and the full response body (including error.code and additional fields); for an interrupted stream, the last few events received
API key name The name only
Client Name and version of the tool or SDK; for timeouts, the client's timeout settings; for IP allowlist problems, the egress IP
Related identifiers Task ID, session ID and upstream request ID, if any

Redact before sending:

  • Do not send the API key in plaintext, the full Authorization or x-api-key request header, or the BYOK keys you hold with providers.
  • Delete or replace personal information and business data in prompts, answers and uploaded files; when a minimal reproduction can show the problem, do not attach the original content.
  • Content copied from Raw packets in the logs excludes credential headers, but the body may contain sensitive information; check it before sending.