Skip to content

Errors & Troubleshooting

Applies to: Developers Updated: 2026-07-02

This guide explains the meaning of the various error codes CloudRouter returns, how to tell "whose problem it is", and the recommended retry and timeout strategies.


1. Error code quick reference

HTTP codeError codeMeaningWhat you should do
400invalid_request_errorInvalid request parametersCheck the request body format and parameters
401authentication_errorAPI Key invalid or missingCheck the Authorization: Bearer header
403Balance/quota class (see note below)Insufficient account balance or quota cappedContact the owning Organization to top up / raise the quota
403Key expiredAPI Key expiredContact the Organization to redistribute the Key
429API_KEY_RATE_{5H,1D,7D}_EXCEEDEDKey's rate limit exhausted (5h / 1d / 7d window)Wait for the rate-limit window to reset or raise the quota
429Quota / concurrency class (see note below)Key quota exhausted or concurrency exceededWait for the window to reset / reduce concurrency / contact the Organization to adjust quota
502upstream_errorModel provider returned 5xx, mapped uniformlyRetry later
500internal_server_errorCloudRouter platform's own failureContact technical support

⚠️ About the specific error code strings for 403/429: the individual error codes for scenarios like Organization balance exhausted, Subuser quota used up, Key quota exhausted, or concurrency exceeded — rely on the code field actually returned by the API, and do not hard-code these strings for exact matching. The reliable approach is to classify by HTTP status code: balance/quota cap is 403, rate/throttle/concurrency is 429. The three rate-limit codes API_KEY_RATE_{5H,1D,7D}_EXCEEDED are confirmed stable and safe to use.

About the 429 breakdown: rate-limit exhaustion returns API_KEY_RATE_5H_EXCEEDED / API_KEY_RATE_1D_EXCEEDED / API_KEY_RATE_7D_EXCEEDED per time window — just wait for the window to reset; quota exhaustion / concurrency exceeded require adjusting the quota or reducing concurrency.

Key design 1: the model provider's 5xx is mapped uniformly to CloudRouter's 502; only a failure of the CloudRouter platform itself returns 500.

Key design 2: be careful to distinguish 403 insufficient balance from 429 rate/throttle — the former means "out of money" (solved by topping up), the latter means "a quota/frequency limit was hit" (wait for the window to reset or adjust the quota). The two are handled completely differently.

⚠️ Special errors for fingerprint calls: a fingerprint is a short identifier the platform automatically assigns to each group; it is fixed and unchanging, and you can view it on the "Call Guide" page. When you use a fingerprint call name to call out a group, if that group is not within your account's available range or its channel is unavailable, the platform returns an error directly — it does not auto-switch, does not degrade, and does not fall back. Handle retries or switch to an available group on the client side; for the mechanics see Call Guide & Dual Routing.


2. Error response body formats

CloudRouter's error response body has multiple shapes; your error parsing must handle all of them.

Shape A: API gateway validation class (nested error object structure)

400 parameter errors, 401 authentication failures, 502 model provider failures, etc. are returned by the API gateway, with the error info inside the error object. Note: whether the outermost type: "error" is present depends on whether the Anthropic-compatible or the OpenAI-compatible endpoint was hit — the same endpoint with different groups can have different outer structures:

json
// Anthropic-compatible endpoint (e.g. routing to an Anthropic-family group)
{
  "type": "error",
  "error": { "type": "upstream_error", "message": "Upstream service temporarily unavailable" }
}

// OpenAI-compatible endpoint (e.g. routing to an OpenAI-family group) — no outermost type
{
  "error": { "type": "invalid_request_error", "message": "..." }
}

Parsing tip: uniformly read error.type and error.message; do not depend on whether the outermost type field exists. The fields inside the error object are identical across both endpoints.

Common error.type values:

error.typeCorresponding scenario
invalid_request_error400 parameter error
authentication_error401 authentication failure
upstream_error502 model provider failure

Shape B: authentication / billing / rate-limit class (top-level code / message structure)

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

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

Shape C: 500 platform internal failure

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

⚠️ Parsing reminder: when doing fine-grained error handling, don't only read error.type — for the most common 4xx business errors like insufficient balance, rate limit, and quota, the error code is in the top-level code field (Shape B), not error.type (Shape A). It's recommended to handle both the top-level code and error.type; 500 is code (integer) + reason. The exact fields are as actually returned by the API.


3. Determining "whose problem this is"

After receiving an error, judge the direction by the HTTP status code:

  • 4xx — the request itself has a problem (parameter error, authentication failure, insufficient balance, rate limit exceeded). Check the request content. If you used a fingerprint but got "group unreachable", it means the group is out of your available range or currently unavailable (no auto-degradation) — switch to an available group or contact the platform.
  • 500 — a failure of the CloudRouter platform itself; please contact customer support.
  • 502 — a failure on the model provider side (provider 5xx is mapped uniformly to 502); please retry later.

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


python
import time
from openai import OpenAI

client = OpenAI(api_key="YOUR_API_KEY", base_url="https://api.cloudrouter.online/v1")

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)
            # Don't retry 4xx client errors (retrying is pointless)
            if status and 400 <= status < 500 and status != 429:
                raise
            # Exponential backoff retry for 429/502/500
            if attempt < max_retries - 1:
                wait = 2 ** attempt   # 1s, 2s, 4s
                time.sleep(wait)
            else:
                raise

Principles:

  • Don't retry 4xx (except 429) — parameter/authentication/balance/Key-expired issues, fingerprint group unreachable, etc. gain nothing from retrying; handle them by error type (check parameters, contact the 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
  • Cap the maximum retries — usually 3, to avoid infinite retrying

5. Special handling for streaming (SSE) scenarios

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

text
data: {"choices":[{"delta":{"content":"first half of the content"}}]}
data: {"type":"error","error":{"type":"upstream_error","message":"..."}}

after which the connection drops. Handling tips:

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

6. What to provide when seeking technical support

When contacting CloudRouter support, including the following information speeds up diagnosis:

  • The timestamp of the error (to the minute, including time zone)
  • The model call name used (bare or with fingerprint) and the endpoint
  • The HTTP status code and the full error response body
  • Whether it was streaming (stream)
  • The approximate call frequency (helps determine whether it was throttling)

Contact us