首页 / 文章 / API 常见错误码排查:401 到 503

API 常见错误码排查:401 到 503

按状态码拆开 401、403、404、429、500、503 的常见成因,说明 request id 怎么用,并给出一段只在可重试状态码上退避的 Python 封装。

先把 request id 拿到

出错时最先记下的不是错误文案,是 request id。多数实现把它放在响应头,常见名字是 x-request-id,网关也可能带自己的前缀,具体头名以实际响应为准。它能把一次失败请求和上游日志对上,报障时贴这一串比贴整段报错有用。

同时记下时间、模型名、分组、状态码和响应体前 500 字。这五项凑齐,多数问题自己就能判断,不用来回复述现象。

日志里把 request id 和业务单号打在同一行,出问题时可以从业务侧反查到底是哪一次调用。

401 与 403

401 是身份没通过:key 拼错、被删除、Authorization 头少了 Bearer 前缀、中间多了空格或换行。复制 key 时最常见的坑是尾部带了一个空格,肉眼看不出来。

403 是身份通过了但没权限:分组不支持这个模型、账户额度用完、IP 白名单拦了、key 的作用范围不含该接口。先看模型页列出的可用分组,比自己猜快。

分不清两者时,用同一个 key 请求 /v1/models:能列出模型说明身份没问题,问题在权限或分组;列不出来就是 key 本身无效。这一步能省掉大半排查时间。

404

404 基本是路径或名字的问题。base_url 要填到 /v1,请求路径是 /chat/completions,拼起来是 https://ai.idcidiot.com/v1/chat/completions。多一层或少一层 /v1 都会 404。

模型名要和 定价页 上完全一致,大小写和连字符都算。claude-sonnet-5 写成 claude-sonnet-5.0 不会自动纠正,模型清单可以对着 模型总览 核。

还有一种 404 来自反向代理:nginx 没配好路径转发,请求根本没到网关。用 curl -i 看响应头里的 server 字段,能区分是不是网关返回的。

429

429 是限流。两条线:请求数(RPM)和 token 数(TPM),长请求更容易先撞 TPM。响应里通常带 Retry-After,按它等比自己猜间隔准。

并发高时 429 会连锁:一次失败触发重试,重试又加剧拥堵。退避要加随机抖动,别让所有客户端在同一秒重发。

余额或配额不足有时也用 429 返回,具体看响应体里的 code 和 message,别只看状态码。

限流窗口一般按分钟滚动,等满一个窗口再发,比零散重试恢复得快。批量任务把请求摊到更长的时间段,比猛提并发更稳。

500 与 503

500 是上游或网关内部错误,重试一次通常能过。503 多是渠道暂时不可用或过载,换分组、换模型往往立刻恢复。

连续 500 不要死磕同一个模型,先切到备用型号,把失败样本记下来。重试会重新发一遍输入 token,claude-sonnet-5 在 Claude Max 分组输入 2.55 美元每百万 token,一次 4 万 token 的请求重试三次就是 0.306 美元,成本要算进预算。

流式请求更麻烦:HTTP 状态码已经是 200,错误藏在 SSE 的 error 事件里。客户端要监听数据流里的错误对象,只看状态码会漏掉半路失败。

一张对照表和重试封装

状态码常见原因先查什么
401key 错误或被删头是否为 Bearer sk-...,尾部有无空格
403分组无权限、额度或 IP 限制模型页的可用分组、账户余额
404路径或模型名写错base_url 是否含 /v1,模型名是否一致
429触发 RPM 或 TPM 限流响应体的 Retry-After 与错误码
500上游异常或网关错误request id,隔几秒重试一次
503渠道不可用或过载换分组、换模型
python
import time
import requests

RETRYABLE = {429, 500, 502, 503, 504}

def post(payload, tries=4):
    for i in range(tries):
        r = requests.post(
            "https://ai.idcidiot.com/v1/chat/completions",
            headers={"Authorization": "Bearer sk-..."},
            json=payload,
            timeout=90,
        )
        rid = r.headers.get("x-request-id", "-")
        if r.status_code < 400:
            return r.json()

        print(f"{r.status_code} request_id={rid} {r.text[:300]}")
        if r.status_code not in RETRYABLE or i == tries - 1:
            raise RuntimeError(f"{r.status_code} request_id={rid}")

        wait = 1.5 ** i
        retry_after = r.headers.get("retry-after", "")
        if retry_after.isdigit():
            wait = max(wait, int(retry_after))
        time.sleep(wait + 0.4 * i)

400 和 422 不要重试,它们的成因在请求体里,重发一百次结果一样。把这类错误单独打日志,按模型和字段聚合,能很快看出是哪段提示词或哪个参数不稳定。

重试次数设上限,总时长也设上限。一个请求卡住三分钟再失败,比立刻失败更伤,上游的资源已经占住了。

用 二五云API 跑通这些模型

OpenAI 兼容接口,一个 Key 调用 GPT、Claude、Gemini、DeepSeek、Kimi 等模型,按量计费。

免费注册查看模型价格

相关文章