大模型 API 错误码速查:400 到 529 各代表什么、哪些该重试
大模型 API 错误码可以先按一条线分开:4xx 基本是请求本身的问题,原样重试没有用,要改请求、换密钥或者等额度;5xx 和 524、529 多半是服务商或中间链路的问题,可以带退避重试。例外是 429:它是 4xx,但通常值得等一会儿再试,前提是先分清“速率超了”还是“余额没了”。
下面先给总表,再讲每一类该怎么确认,最后给一段重试逻辑的示例。各厂商对同一个状态码的细分不完全一样,表里写的是常见含义,具体以各家官方错误码文档为准。
一张表:每个状态码是谁的问题、能不能重试
| 状态码 | 常见含义 | 通常是谁的问题 | 能否重试 | 建议等待 |
|---|---|---|---|---|
| 400 | 请求格式或参数不对,例如 JSON 结构错、参数超出范围、上下文超长 | 客户端 | 否,先改请求 | — |
| 401 | 密钥无效、缺失、已吊销,或请求头写错 | 客户端 | 否 | — |
| 402 | 余额不足(DeepSeek 等文档里单列;部分厂商用 400 或 429 表达) | 账户 | 否,先充值 | — |
| 403 | 没有权限:密钥无权访问该资源,或所在地区不在服务范围内 | 账户 / 地区政策 | 否 | — |
| 404 | 接口路径或模型名写错,或该账户看不到这个模型 | 客户端 | 否 | — |
| 413 | 请求体太大 | 客户端 | 否,拆小 | — |
| 422 | 参数语义不合法(DeepSeek 等文档单列) | 客户端 | 否 | — |
| 429 | 速率或并发超限;也可能是额度用完 | 客户端用量 / 账户 | 速率类可以,额度类不行 | 优先按 retry-after 头 |
| 500 | 服务端内部错误 | 服务商 | 可以 | 例如从 1 秒起指数退避 |
| 502 | 网关拿到了上游的无效响应 | 中间链路或服务商 | 可以 | 同上 |
| 503 | 服务暂不可用或过载 | 服务商 | 可以 | 同上,持续出现就降级 |
| 504 | 网关等上游超时 | 中间链路或服务商 | 可以,但先检查请求是否太长 | 同上 |
| 524 | Cloudflare 已连上源站,但源站在规定时间内没返回 | 源站处理太慢 | 可以,长任务建议改流式 | 同上 |
| 529 | Anthropic 的 overloaded_error,服务整体过载 | 服务商 | 可以 | 退避时间放长一些 |
两个容易误判的点:
- 524 和 529 不是一回事。524 是 Cloudflare 的状态码,只说明“经过 Cloudflare 的那段链路等源站等超时了”,源站可能是官方 API,也可能是你自己或中转服务的服务器。529 是 Anthropic 文档里定义的过载码,出现时说明请求已经到了 Anthropic,是对方容量不足。
- 429 有两种。OpenAI 的 429 响应里,
rate_limit_exceeded是速率超限,等一下就好;insufficient_quota是额度或账单问题,重试多少次都一样。Anthropic 的 429 是rate_limit_error,响应头里带retry-after。
看到报错,先看哪三样东西?
状态码只是第一层信息。能定位问题的是下面三样,建议在日志里把它们和状态码一起记下来。
1. 响应体里的错误类型
主流接口的错误响应都是 JSON,里面有一个类型字段:
- OpenAI 格式:
error.type、error.code、error.message - Anthropic 格式:顶层
type: "error",error.type是invalid_request_error、authentication_error、permission_error、not_found_error、rate_limit_error、api_error、overloaded_error这类值
同样是 400,error.message 可能写的是上下文超长,也可能是某个参数名拼错,处理方法完全不同。只记状态码不记 message,事后基本没法查。
2. request_id
OpenAI 在响应头 x-request-id 里返回请求 ID,Anthropic 在响应头 request-id 里返回(响应体里通常也有)。找官方支持或者对比自己的服务端日志时,靠这个 ID 才能精确对上某一次请求。
3. 响应是谁发出来的
502、504、524 这类码经常不是模型服务商发的,而是中间某一层:公司代理、反向代理、CDN、中转网关。判断方法:
# 只看响应头,确认是谁回的错误
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 '{}'
上面故意发一个空请求体,正常应该收到 400 加上 request-id 头,说明网络链路通、请求确实到了官方。如果收到的是一个 HTML 页面、server: cloudflare 且没有任何请求 ID,或者是你代理软件自己的报错页,那问题在链路上,不在模型。OpenAI 也一样,可以对 https://api.openai.com/v1/models 发不带密钥的请求,预期是 401 加 x-request-id。
4xx:怎么改请求,而不是盲目重试?
排查顺序可以这样走:
- 401:检查环境变量是否真的被读到(
echo ${#OPENAI_API_KEY}看长度,不要把密钥打印出来);检查请求头写法,OpenAI 格式用Authorization: Bearer,Anthropic 格式用x-api-key。用中转或自定义接口地址时,接口地址和密钥要配套,详细配置见Claude Code 自定义 API 与 Codex、OpenCode 接口地址配置。 - 404:多数是 base URL 少了或多了
/v1,或者模型名拼写不对。 - 400 / 413 / 422:读
error.message。上下文超长就截断历史或换上下文更长的模型;参数问题对照文档逐个检查。 - 403:可能是密钥权限不够,也可能是服务所在地区政策的限制。后者请按官方说明处理,遵守服务条款和当地法规,参见Claude 提示所在地区不受支持:原因、官方政策与合规选择。
- 429:先区分类型。速率类按
retry-after等待,并在客户端加并发上限;额度类去控制台看余额和用量限制。
4xx 一律不要进入自动重试循环。一个参数写错的 400 被重试 5 次,只会多 5 条一样的错误日志;OpenAI 的速率限制文档还说明,失败的请求同样计入每分钟限额。
5xx、524、529:是不是全局故障?
服务端错误能重试,但先要回答:只有我这样,还是大家都这样?这决定了你是继续排查自己的链路,还是等官方恢复。
三步判断
- 看官方状态页和第三方监测。打开 cdnping 的 API 状态页,它从 Cloudflare 边缘每 5 分钟探测一次各家官方 API 入口,并每 15 分钟同步 OpenAI、Anthropic、Moonshot、Groq 等的官方状态页。如果是 Claude,直接看 /status/anthropic。状态页上的事件等级怎么理解,可以看怎么看 OpenAI 状态页和 Claude 状态页。
- 看用户侧反馈。官方状态页通常比实际故障晚一些才更新。挂了吗页面综合了官方状态、每 5 分钟的 API 探测和用户一键报告(打不开、很慢、限流等),用户报告突然变多往往是更早的信号。
- 从自己这边测一次。在在线测速里测一下目标 API 的首次连接和往返。连接本身就失败或者很慢,问题更可能在本地网络或代理;连接正常而请求返回 5xx,更可能在服务商。分层检查方法见ChatGPT 挂了吗?三步判断是服务故障还是自己的网络问题和Claude Code 连接超时和报错怎么排查。
5xx 事件有多常见?
按 cdnping 从各家官方状态页同步的记录,2026-09-17 以来(截至 2026-10-17):OpenAI 有 4 次 major、19 次 minor 级别的事件;Claude 有 6 次 major、1 次 minor;Moonshot 有 8 次 critical。同期 Cloudflare 状态页上也出现过 “Increased HTTP 502 Errors”“Increased HTTP 5xx Errors Ashburn” 这类事件,说明 502、5xx 有时来自 CDN 层,而不是模型服务商。按服务商的逐条梳理见AI 服务故障盘点:2026年9–10月。
一个月的窗口里就有这么多事件,客户端需要有重试和降级,不能假设上游一直可用。
当前各 API 入口可达吗?
cdnping 在 2026-10-17 开始采集,下面是首批探测的结果(Cloudflare 边缘 DEN 节点,UTC 08:40–10:05,共 242 次探测,窗口很短,只能看个大概):
| API 入口 | p50 | p95 | 窗口内成功率 |
|---|---|---|---|
| api.openai.com | 96 ms | 194 ms | 100% |
| api.anthropic.com | 73 ms | 84 ms | 100% |
| generativelanguage.googleapis.com | 69 ms | 89 ms | 100% |
| api.deepseek.com | 353 ms | 414 ms | 100% |
| api.moonshot.cn | 375 ms | 1125 ms | 约 94% |
| dashscope.aliyuncs.com | 615 ms | 1152 ms | 100% |
这是从美国机房测的入口可达性,不代表你本地的体验,也不代表模型推理是否正常;它能回答的是“入口有没有整体不通”。探测口径见数据方法。
重试逻辑怎么写?
把上面的表落到代码里,大致是这样。下面是 Python 示意,send() 和 resp 的属性是假设的接口,按你用的 HTTP 库或 SDK 改写:
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", {})
# 额度类 429 不重试
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 # 过载时等久一点,减少对方压力
time.sleep(delay)
实现时还要注意:
- 加随机抖动。多个进程同时失败、同时按固定间隔重试,会在同一时刻再打一波请求。
- 设总时长上限。交互式场景下用户等不了太久,重试 2–3 次失败就该提示或切到备用模型。
- 流式请求的重试要小心。已经输出了一半再失败,直接重发会重复内容,需要在应用层决定是续写还是重来。
- 504 和 524 反复出现时,先看请求本身。非流式请求生成很长的输出,很容易超过网关的等待时间,改成流式输出往往比重试更有效。
- 日志里记下状态码、错误类型、request_id 和耗时。想进一步统计自己的成功率,可以参考自己测 AI API 的可用率:指标、脚本与口径。
用聚合网关时,错误码怎么归属?
经过网关或中转服务时,你看到的状态码可能是网关自己生成的,也可能是透传的上游错误。判断方法还是看响应体和请求 ID,网关一般会在错误里说明来源。
以 AGI Plan 为例(AGI Plan 是 cdnping 的商业合作方),它公开的可用率口径是“成功 /(成功 + 因平台自身原因失败)”,只有 5xx 计为平台失败,4xx 视为请求方的问题;逐小时数据可以在 https://agiplan.dev/api/status/requests?month=YYYY-MM 查到,不需要登录,cdnping 的 /status/agiplan 也有镜像。评估任何网关时,都可以问同样的问题:它怎么区分 4xx 和 5xx,可用率按什么口径算,数据能不能公开核对。更多检查项见AI API 中转站怎么选:可用率、计费、数据政策 8 项检查。
排查检查表
遇到报错时按顺序过一遍: