Error Codes and Troubleshooting

Applicable role: Developer Last updated: 2026-07-14

This document explains the meaning of the various error codes returned by the platform, how to determine "whose problem it is," and the recommended retry and timeout strategies.


1. Error Code Quick Reference

HTTP Code Error Code Meaning What You Should Do
400 invalid_request_error Invalid request parameters Check the request body format and parameters
401 authentication_error API Key invalid or missing Check the Authorization: Bearer header
403 Balance/quota-related (see notes below) Insufficient account balance or quota cap reached Contact your organization to top up / raise the quota
403 Key expired API Key expired Contact your organization to reissue the Key
403 Default routing configuration invalid The group in the default routing configuration is no longer valid (removed or no longer includes the model) Contact your organization admin to update the default routing configuration or bind a valid group to the Key
429 API_KEY_RATE_{5H,1D,7D}_EXCEEDED Key rate limit exhausted (5h / 1d / 7d window) Wait for the rate limit window to reset or raise the quota
429 Quota / concurrency-related (see notes below) Key quota exhausted or concurrency limit exceeded Wait for the window to reset / reduce concurrency / contact your organization to adjust the quota
502 upstream_error Model provider returned 5xx, mapped uniformly Retry later
500 internal_server_error Platform's own failure Contact technical support

⚠️ About the specific error code strings for 403/429: The error codes for scenarios such as organization balance exhausted, sub-user quota exhausted, Key quota exhausted, and concurrency limit exceeded—should be determined by the code field actually returned by the API. Do not hard-code these strings for exact matching. The reliable approach is to classify by HTTP status code: balance/quota cap is 403, and rate limit/throttling/concurrency is 429. The three rate limit codes API_KEY_RATE_{5H,1D,7D}_EXCEEDED have been confirmed stable and can be used with confidence.

About the 429 subdivisions: Rate limit exhaustion returns API_KEY_RATE_5H_EXCEEDED / API_KEY_RATE_1D_EXCEEDED / API_KEY_RATE_7D_EXCEEDED based on the time window—just wait for the window to reset. Quota exhaustion / concurrency limit exceeded requires adjusting the quota or reducing concurrency.

Key design 1: A model provider's 5xx is uniformly mapped to the platform's 502; only the platform's own failures return 500.

Key design 2: Be careful to distinguish between 403 insufficient balance and 429 rate limit/throttling—the former means "out of money" (resolved by topping up), while the latter means "triggered a quota/frequency limit" (wait for the window to reset or adjust the quota). The two are handled in completely different ways.

⚠️ Special errors when calling with a group identifier: Group identifier routing is an advanced feature (disabled by default) and can only be used after your organization enables it. A group identifier is a short identifier automatically assigned by the platform to each group; it is fixed and unchanging, and once enabled it can be viewed and copied on the "Usage Guide" page. When targeting a group by using a call name with a group identifier, if that group is not within your account's available scope, or the corresponding channel is unavailable, the platform returns an error directly—it does not automatically switch, downgrade, or fall back. Please implement retries on the client side or switch to an available group. For the mechanism, see Usage Guide and Routing.

⚠️ Default routing configuration-related errors: If a Key is not bound to a routing group and is called using a model name, the platform routes according to the default routing configuration. When the group in the default routing configuration has been removed or no longer includes the target model, a 403 error is returned. In this case, contact your organization admin to update the default routing configuration, or bind a valid routing group to the Key.


2. Error Response Body Format

The platform's error response body comes in multiple forms, and error parsing needs to be compatible with all of them.

Form A: Request validation type (nested error object structure)

400 parameter errors, 401 authentication failures, 502 model provider failures, etc. are returned by the platform, with the error information inside the error object. Note: Whether the outermost type: "error" is present depends on whether the Anthropic-compatible endpoint or the OpenAI-compatible endpoint is hit—for the same endpoint but different groups, the outer structure differs:

// Anthropic 兼容端点(如走 Anthropic 系分组)
{
  "type": "error",
  "error": { "type": "upstream_error", "message": "Upstream service temporarily unavailable" }
}
 
// OpenAI 兼容端点(如走 OpenAI 系分组)—— 没有最外层 type
{
  "error": { "type": "invalid_request_error", "message": "..." }
}

Parsing recommendation: Uniformly read error.type and error.message; do not rely on whether the outermost type field exists. The fields inside the error object are consistent across both endpoints.

Common error.type values:

error.type Corresponding Scenario
invalid_request_error 400 parameter error
authentication_error 401 authentication failure
upstream_error 502 model provider failure

Form B: Authentication / billing / rate limit type (top-level code / message structure)

The most frequent business errors—403 balance/quota, 429 rate limit/quota, etc.—use a different structure: the error code is in the top-level code field (a string), with no outer type/error wrapper:

{
  "code": "API_KEY_RATE_5H_EXCEEDED",
  "message": "rate limit exceeded"
}

Form C: 500 platform internal failure

{
  "code": 500,
  "reason": "internal_server_error",
  "message": "internal error"
}

⚠️ Parsing reminder: When doing fine-grained error handling, do not read only error.type—for the most common 4xx business errors such as insufficient balance, rate limit, and quota, the error code is in the top-level code field (Form B), not error.type (Form A). It is recommended to handle both the top-level code and error.type fields; for 500, it is code (integer) + reason. The exact fields should be determined by what the API actually returns.


3. Determining "Whose Problem This Is"

After receiving an error, determine the direction based on the HTTP status code:

  • 4xx — There is a problem with the request itself (parameter error, authentication failure, insufficient balance, rate limit exceeded, invalid default routing configuration). Check the request content. If a group identifier is provided but "group unreachable" is reported (group identifier routing must be enabled), it means the group is not within the available scope or is currently unavailable (no automatic downgrade); please switch to an available group or contact the platform. If you are using default routing and an error is reported, the group in the default routing configuration may have become invalid; please contact your organization admin to update the configuration.
  • 500 — The platform's own failure; please contact customer support.
  • 502 — A failure on the model provider side (provider 5xx is uniformly mapped to 502); please retry later.

When unsure whether it is a platform or model provider failure, first confirm the error code: 502 points to the model provider, and 500 points to the platform itself.


import time
from openai import OpenAI
 
client = OpenAI(api_key="YOUR_API_KEY", base_url="YOUR_API_BASE_URL")
 
def chat_with_retry(messages, max_retries=3):
    for attempt in range(max_retries):
        try:
            return client.chat.completions.create(
                model="claude-sonnet-4-6",
                messages=messages,
                timeout=60
            )
        except Exception as e:
            status = getattr(e, "status_code", None)
            # 4xx 客户端错误不重试(重试也没用)
            if status and 400 <= status < 500 and status != 429:
                raise
            # 429/502/500 指数退避重试
            if attempt < max_retries - 1:
                wait = 2 ** attempt   # 1s, 2s, 4s
                time.sleep(wait)
            else:
                raise

Principles:

  • Do not retry 4xx (except 429)—for problems like parameter/authentication/balance/Key expiration, and group unreachable with a group identifier, retrying is meaningless; handle them by error type (check parameters, contact your organization to top up or reissue the Key, switch to an available group, etc.)
  • Only retry 429 / 502 / 500—use exponential backoff (1s→2s→4s) to avoid excessive requests
  • Set a timeout—60s is recommended to avoid requests hanging indefinitely
  • Limit the maximum number of retries—usually 3, to avoid infinite retries

5. Special Handling for Streaming (SSE) Scenarios

When a streaming request errors out midway, you will first receive partial content chunks and then an error event:

data: {"choices":[{"delta":{"content":"前半段内容"}}]}
data: {"type":"error","error":{"type":"upstream_error","message":"..."}}

The connection then closes. Handling recommendations:

  • Identify the error event separately in your SSE parsing logic; do not treat it as normal content
  • The "half-rendered content" already displayed on the client requires the business layer to decide how to handle it (clear it / mark it as interrupted / allow regeneration)
  • This is the scenario most prone to pitfalls in streaming calls; it is recommended to encapsulate unified streaming error handling

6. What to Provide When Seeking Technical Support

When contacting platform support, including the following information can speed up diagnosis:

  • The timestamp of the error (accurate to the minute, including timezone)
  • The model call name used (model name or with group identifier) and the endpoint
  • The HTTP status code and the complete error response body
  • Whether it is streaming (stream)
  • The approximate call frequency (helps determine whether throttling occurred)