AI API Error Codes 400 to 529: What Each Means and Which to Retry

Blog / Troubleshooting

AI API Error Codes 400 to 529: What Each Means and Which to Retry

You can split LLM API error codes along one line. 4xx errors are basically problems with the request itself: retrying it unchanged is pointless, so fix the request, swap the key, or wait for quota. 5xx, 524 and 529 are mostly problems on the provider's side or somewhere along the path, and are worth retrying with backoff. The exception is 429. It is a 4xx, but it is usually worth waiting a bit and trying again, as long as you first tell apart "you exceeded the rate limit" from "your balance ran out".

Below is a summary table, then how to confirm each class, and finally an example of retry logic. Providers do not break down the same status code in exactly the same way. The table lists common meanings; defer to each vendor's official error-code documentation for specifics.

One table: whose problem is each status code, and can you retry?

StatusCommon meaningUsually whose problemRetry?Suggested wait
400Malformed request or bad parameters, e.g. broken JSON, parameter out of range, context too longClientNo, fix the request first—
401Invalid, missing or revoked key, or wrong request headerClientNo—
402Insufficient balance (listed separately in DeepSeek's docs and others; some providers use 400 or 429 for this)AccountNo, top up first—
403No permission: the key cannot access the resource, or your region is not in the service areaAccount / regional policyNo—
404Wrong endpoint path or model name, or the account cannot see that modelClientNo—
413Request body too largeClientNo, split it up—
422Semantically invalid parameters (listed separately in DeepSeek's docs and others)ClientNo—
429Rate or concurrency limit exceeded; could also mean quota exhaustedClient usage / accountRate-limit type yes, quota type noPrefer the retry-after header
500Internal server errorProviderYese.g. exponential backoff starting at 1 second
502Gateway received an invalid response from upstreamIntermediate hop or providerYesSame
503Service temporarily unavailable or overloadedProviderYesSame; if it persists, degrade gracefully
504Gateway timed out waiting for upstreamIntermediate hop or providerYes, but first check whether the request is too longSame
524Cloudflare connected to the origin, but the origin did not respond within the time limitOrigin is too slowYes; for long jobs, switch to streamingSame
529Anthropic's overloaded_error: the service as a whole is overloadedProviderYesUse a longer backoff

Two points that are easy to get wrong:

  • 524 and 529 are not the same thing. 524 is a Cloudflare status code. It only says that the leg of the path going through Cloudflare timed out waiting for the origin, and that origin could be the official API, or it could be your own server or a relay service's server. 529 is an overload code defined in Anthropic's documentation. When you see it, the request has already reached Anthropic and they are out of capacity.
  • There are two kinds of 429. In an OpenAI 429 response, rate_limit_exceeded is a rate limit, and waiting a moment fixes it; insufficient_quota is a quota or billing problem, and no number of retries will change that. Anthropic's 429 is rate_limit_error, and the response headers carry retry-after.

You see an error: which three things do you check first?

The status code is only the first layer of information. These three things are what let you pin down the problem, and you should log them together with the status code.

1. The error type in the response body

Error responses from the major APIs are all JSON and include a type field:

  • OpenAI format: error.type, error.code, error.message
  • Anthropic format: top-level type: "error", and error.type is a value such as invalid_request_error, authentication_error, permission_error, not_found_error, rate_limit_error, api_error or overloaded_error

For the same 400, error.message might say the context is too long, or that a parameter name is misspelled, and the fixes are completely different. If you log only the status code and not the message, there is almost no way to investigate afterward.

2. request_id

OpenAI returns the request ID in the x-request-id response header; Anthropic returns it in the request-id response header (and it is usually in the response body too). When you contact official support or compare against your own server logs, this ID is what lets you match one specific request exactly.

3. Who actually sent the response

Codes like 502, 504 and 524 often do not come from the model provider, but from some layer in between: a corporate proxy, a reverse proxy, a CDN, a relay gateway. To tell:

# Look at response headers only, to see who returned the error
curl -sS -D - -o /dev/null https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{}'

The command above deliberately sends an empty body. You should normally get a 400 plus a request-id header, which means the network path works and the request really reached the official service. If you get an HTML page, or server: cloudflare with no request ID at all, or an error page from your own proxy software, the problem is on the path and not in the model. OpenAI works the same way: send a request with no key to https://api.openai.com/v1/models, and you should get a 401 plus x-request-id.

4xx: how do you change the request instead of blindly retrying?

You can work through the investigation in this order:

  1. 401: check that the environment variable is actually being read (echo ${#OPENAI_API_KEY} prints its length; do not print the key itself). Check the header format: OpenAI-style APIs use Authorization: Bearer, Anthropic-style APIs use x-api-key. If you use a relay or a custom endpoint, the endpoint URL and the key must match. For detailed setup, see Configuring a custom API endpoint for Claude Code, Codex and OpenCode.
  2. 404: most often the base URL is missing or has an extra /v1, or the model name is misspelled.
  3. 400 / 413 / 422: read error.message. If the context is too long, truncate the history or switch to a model with a longer context; for parameter problems, check them one by one against the docs.
  4. 403: it may be that the key lacks permissions, or that regional policy for the place you are in applies. For the latter, follow the provider's official guidance and comply with its terms of service and local law; see Claude says your region is unsupported: causes, official policy and compliant options.
  5. 429: first work out which type it is. For rate limits, wait according to retry-after and add a concurrency cap on the client; for quota, check your balance and usage limits in the console.

Never put 4xx errors into an automatic retry loop. A 400 caused by a wrong parameter, retried 5 times, just gives you 5 more identical error logs; OpenAI's rate-limit documentation also states that failed requests count toward the per-minute limit as well.

5xx, 524, 529: is it a global outage?

Server-side errors can be retried, but first answer one question: is it just me, or is it everyone? That decides whether you keep debugging your own path or wait for the provider to recover.

Three steps to tell

  1. Check the official status pages and third-party monitoring. Open cdnping's API status page. It probes each provider's official API endpoints from the Cloudflare edge every 5 minutes, and syncs the official status pages of OpenAI, Anthropic, Kimi (Moonshot AI), Groq and others every 15 minutes. For Claude, go straight to /en/status/anthropic. For how to interpret incident severity on those pages, see How to read the OpenAI and Claude status pages.
  2. Check user-side reports. Official status pages usually update somewhat after the actual outage starts. The Is it down? page combines official status, the 5-minute API probes and one-click user reports (can't open, slow, rate-limited, and so on); a sudden jump in user reports is often the earlier signal.
  3. Run a test from your own side. Use the online speed test to measure first-connection time and round trip to the target API. If the connection itself fails or is slow, the problem is more likely your local network or proxy; if the connection is fine but the request returns 5xx, it is more likely the provider. For the layered checking method, see Is ChatGPT down? Three steps to tell a service outage from your own network problem and Troubleshooting Claude Code connection timeouts and errors.

How common are 5xx incidents?

According to the records cdnping syncs from each provider's official status page, from 2026-09-17 to 2026-10-17: OpenAI had 4 incidents at major level and 19 at minor level; Claude had 6 major and 1 minor; Kimi (Moonshot AI) had 8 critical. Over the same period the Cloudflare status page also showed incidents such as "Increased HTTP 502 Errors" and "Increased HTTP 5xx Errors Ashburn", which shows that 502 and other 5xx errors sometimes come from the CDN layer rather than the model provider. For a provider-by-provider breakdown, see AI service incident roundup: September-October 2026.

With this many incidents in a one-month window, clients need retries and fallbacks; do not assume the upstream is always available.

Are the API endpoints reachable right now?

cdnping began collecting on 2026-10-17. Below are the results of the first batch of probes (Cloudflare edge DEN node, UTC 08:40-10:05, 242 probes in total; the window is very short, so treat it as a rough picture only):

API endpointp50p95Success rate in window
api.openai.com96 ms194 ms100%
api.anthropic.com73 ms84 ms100%
generativelanguage.googleapis.com69 ms89 ms100%
api.deepseek.com353 ms414 ms100%
api.moonshot.cn375 ms1125 msabout 94%
dashscope.aliyuncs.com (Alibaba Cloud Model Studio, Qwen)615 ms1152 ms100%

These were measured from a US data center, so they reflect endpoint reachability, not your local experience, and not whether model inference is healthy. What they can answer is "is the endpoint down as a whole?" For the probing methodology, see Methodology.

How should you write the retry logic?

Putting the table above into code looks roughly like this. The following is a Python sketch; send() and the attributes of resp are assumed interfaces, so adapt them to the HTTP library or SDK you use:

import random, time

RETRYABLE = {500, 502, 503, 504, 524, 529}

def should_retry(status, body):
    if status in RETRYABLE:
        return True
    if status == 429:
        err = (body or {}).get("error", {})
        # Quota-type 429: do not retry
        return "insufficient_quota" not in (err.get("code"), err.get("type"))
    return False

def call_with_retry(send, max_attempts=5, base=1.0, cap=30.0):
    for attempt in range(max_attempts):
        resp = send()
        if resp.status < 400:
            return resp
        body = resp.json_or_none()
        if not should_retry(resp.status, body) or attempt == max_attempts - 1:
            rid = resp.headers.get("request-id") or resp.headers.get("x-request-id")
            raise RuntimeError(f"{resp.status} {rid} {body}")
        retry_after = resp.headers.get("retry-after")
        if retry_after and retry_after.isdigit():
            delay = float(retry_after)
        else:
            delay = min(cap, base * 2 ** attempt) * random.uniform(0.5, 1.0)
        if resp.status == 529:
            delay *= 2  # Wait longer when overloaded, to reduce pressure on the other side
        time.sleep(delay)

A few more things to watch when implementing this:

  • Add random jitter. If many processes fail at the same moment and retry at the same fixed interval, they will hit the service with another wave at the same instant.
  • Set an overall time limit. In interactive scenarios users cannot wait long; after 2-3 failed retries, show a message or switch to a backup model.
  • Be careful retrying streaming requests. If the output is half done when it fails, resending directly will duplicate content, and the application layer has to decide whether to continue or start over.
  • When 504 and 524 keep recurring, look at the request itself first. A non-streaming request that generates very long output easily exceeds the gateway's wait time, and switching to streaming is often more effective than retrying.
  • Log the status code, error type, request_id and duration. To go further and measure your own success rate, see Measuring AI API uptime yourself: metrics, scripts and definitions.

When you use an aggregation gateway, who owns the error code?

When requests go through a gateway or relay service, the status code you see may be generated by the gateway itself, or it may be an upstream error passed through. The method is still to look at the response body and the request ID; gateways generally say in the error where it came from.

Take AGI Plan as an example (AGI Plan is a commercial partner of cdnping). Its published availability definition is "successes / (successes + failures caused by the platform itself)", where only 5xx counts as a platform failure and 4xx is treated as the requester's problem. Hourly data is available at https://agiplan.dev/api/status/requests?month=YYYY-MM with no login required, and cdnping's /en/status/agiplan mirrors it. For any gateway you evaluate, you can ask the same questions: how does it distinguish 4xx from 5xx, what definition does its availability use, and can the data be checked publicly? For more checklist items, see How to choose an AI API relay: 8 checks on availability, billing and data policy.

Troubleshooting checklist

When an error comes up, go through these in order:

  • Record the status code, error.type / error.code, error.message and request_id
  • 4xx: fix the request per the table, check the key, check the balance, and do not auto-retry (except rate-limit 429)
  • Confirm whether the response came from the official service or an intermediate layer (look at response headers and the request ID)
  • 5xx / 524 / 529: open /en/status and /en/down to see whether there is a wide outage
  • Run a connection test with the online speed test to rule out your local network
  • Retry with exponential backoff plus jitter, respect retry-after, and set an overall time limit
  • When 504 / 524 keep recurring, check output length and consider switching to streaming

Related articles

Keep reading