Claude Code 接入第三方 API 时,大多数报错不是模型问题,而是配置、鉴权或网络问题:刚配好就 401、换了 Base URL 变 404、任务跑一半 429、长任务卡住直到超时。处理顺序是先看状态码和错误类型,再看 request-id,最后才改提示词。本文按 401、404、429、上下文超限和超时拆开,给出排查步骤、日志清单和示例代码。模型与计费以模型价格为准。
说明:Claude、Claude Code、Anthropic 是其权利人的商标。错误类型和接口行为可能随版本调整,本文以 2026 年 10 月的常见情况为例,最终以官方文档为准。
一、先分层:错误发生在哪一层
请求要经过客户端、网络、网关和上游模型四层。同一个 401 可能是 Key 错,也可能是鉴权头不匹配;同一个 404 可能是路径多了 /v1,也可能是模型名不存在。先分层,避免在错误方向反复改配置。
| 状态码 | 错误类型 | 常见原因 | 怎么处理 |
|---|---|---|---|
| 400 | invalid_request_error | 参数、格式、上下文长度或支出限额 | 改请求或调限额后重试 |
| 401 | authentication_error | Key 缺失、错误、过期、鉴权头不匹配 | 修凭证,不重试 |
| 402 | billing_error | 账单或支付信息有问题 | 查账单 |
| 403 | permission_error | Key 无模型或项目权限 | 查权限 |
| 404 | not_found_error | 路径或模型名错误 | 查 Base URL 和模型名 |
| 413 | request_too_large | 请求体超过接口限制 | 拆分请求 |
| 429 | rate_limit_error | 频率、并发或支出上限 | 退避后重试 |
| 500 | api_error | 服务端内部错误 | 退避重试 |
| 504 | timeout_error | 处理超时 | 改流式或分批 |
| 529 | overloaded_error | 服务端过载 | 退避、降并发 |
响应头里的 request-id 要保留,错误响应体里通常也有 request_id。找服务方排查时,一个请求 ID 比十张截图有用。日志至少记录时间、状态码、错误类型、模型名和请求 ID,不要记录完整 Key 和敏感内容。
二、401 与 403:认证头和 Key
401 表示身份没有通过验证,和余额、模型能力无关。Claude Code 有两个容易混淆的变量:ANTHROPIC_API_KEY 作为 X-Api-Key 发送;ANTHROPIC_AUTH_TOKEN 作为 Authorization: Bearer 发送。网关只接受一种时,用错另一个就会稳定 401,先确认要求,不要两个同时导出。
其他常见原因:Key 前后有空格、换行、引号或全角字符;Key 已删除、过期或属于另一个工作区;Base URL 指向错误环境;同时设置订阅登录和 API Key;企业网络或代理改写鉴权头。
403 通常是权限问题:Key 没开通该模型、没有项目权限、被 IP 白名单拦截,或工作区策略不允许。403 不要重试,先查控制台的模型授权和访问策略。
快速隔离:用同一个 Key 和 Base URL 直连 /v1/messages。直连成功而 Claude Code 失败,问题在客户端配置;直连也失败,问题在 Key、网关或网络。
三、404:Base URL 路径与模型名
404 有两类:路径不对,或资源不存在。Claude Code 走 Anthropic Messages API,通常把 Base URL 配成根地址,由客户端拼接 /v1/messages。如果 Base URL 已经带了 /v1,实际路径可能变成 /v1/v1/messages。
按顺序排查:
- 确认协议:Claude Code 用 Anthropic Messages,不是 OpenAI Chat Completions。
- 检查 Base URL 是否多了或少了
/v1。Claude Code 一般填根地址;OpenAI 兼容客户端一般填带/v1的地址。 - 检查末尾斜杠和大小写,避免双斜杠或路径被截断。
- 到模型价格复制当前模型名;网关别名可能和官方名称不同。
- 用最小请求测试,排除代理和客户端缓存。
错误消息是 model not found 时查模型名和权限;是 not_found_error 且路径明显不对时查 Base URL。
四、429:限流、配额与重试风暴
429 表示请求超过了速率、并发或支出限制。常见原因:每分钟请求数或 Token 数超限;多个服务共用一把 Key;重试没有退避,形成重试风暴;达到账户或工作区支出上限;流量突然爬升触发加速限制。
部分支出上限触发的 429 不带 retry-after,等待不会自动恢复,需要调整限额或充值。先看 retry-after,有就按它等待;没有就用指数退避加随机抖动,并设置最大重试次数。401、403、404、400 不要重试。
注意 SDK 默认重试:Anthropic 官方 SDK 会对连接错误、429 和 5xx 重试两次;业务层再包一层,实际请求次数会叠加。把 max_retries 和业务重试一起规划。
429 和 529 不同:429 先查自己的并发、Key 和配额;529 是服务端过载,应退避、降并发并查看服务状态。
五、400 与 413:上下文超限和请求过大
上下文超限通常返回 400 invalid_request_error,错误消息里会出现 prompt is too long。原因不是模型坏了,而是输入加输出的预算超过了上下文窗口。
处理顺序:
- 请求前用
count_tokens量化输入,不要凭字数猜。 - 裁剪最早的历史,只保留 system、最近几轮和摘要。
- 文档先检索召回相关片段,不要整库放入。
- 长文档按章节拆分,分段处理后再合并。
- 压缩工具输出,只返回必要字段。
- 给输出留空间。
max_tokens只是输出上限,不能解决输入超限。
413 request_too_large 是请求体过大,和上下文长度不是一回事。图片以 base64 内联时尤其容易超限,可以压缩图片、改用文件上传接口,或拆分请求。
400 不一定都是上下文问题。参数不被当前模型支持、thinking 配置不合法、支出限额触发,都可能返回 400。要读错误消息里的 type 和具体字段。
六、超时与断流:流式、代理和 SSL
Claude Code 的单次请求超时由 API_TIMEOUT_MS 控制,默认 600000 毫秒,也就是 10 分钟。慢网络或代理环境可以适当调大,但不要无限增大,否则故障会拖很久才暴露。
长任务优先用流式输出或批处理接口。非流式请求如果预计超过 10 分钟,空闲连接可能被断开,表现为一直卡住或超时。流式请求持续收到数据,连接更稳定。
注意:流式请求可能先返回 HTTP 200,再在 SSE 事件流里发一个 error 事件。客户端只看状态码,会把失败当成成功。要解析流中的错误事件,并把已生成的部分标记为不完整。
代理和证书问题也会表现成超时:公司代理需设置 HTTPS_PROXY 或 HTTP_PROXY;企业 TLS 拦截需信任对应 CA 证书,Node 系客户端常见做法是设置 NODE_EXTRA_CA_CERTS;DNS、IPv6、防火墙和 MTU 也可能导致连接不稳定,换网络或手机热点可以快速判断。网关首字节很慢时,可关注 CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS。
七、日志与支持清单
排查时不要只留一句“报错了”。按下面清单收集信息:
- 发生时间、时区、持续时长。
claude --version和操作系统。- Base URL(保留域名,不带完整 Key)。
- 模型名、是否流式、请求耗时和重试次数。
- HTTP 状态码、错误类型和完整错误消息。
request-id,响应头和响应体里都可能有。- 影响范围:单人、单网络、单项目还是全团队。
- 最小复现:一条 curl 或一个最小仓库;以及同一请求打官方入口的结果。
日志脱敏要具体:Key 只保留前四位和后四位,提示词和代码内容按公司规范处理。
八、示例:按错误类型决定是否重试
下面的示例只对 429、5xx 和网络超时重试;401 和 404 直接失败,避免把配置问题拖成重试风暴。Base URL 和模型名从环境变量读取。
import os
import random
import time
from anthropic import (
Anthropic,
APIConnectionError,
APIStatusError,
APITimeoutError,
AuthenticationError,
NotFoundError,
RateLimitError,
)
client = Anthropic(
base_url=os.environ["ANTHROPIC_BASE_URL"],
api_key=os.environ["ANTHROPIC_API_KEY"],
)
def ask(prompt: str, retries: int = 4) -> str:
for attempt in range(retries):
try:
resp = client.messages.create(
model=os.environ["ANTHROPIC_MODEL"],
max_tokens=512,
messages=[{"role": "user", "content": prompt}],
)
return resp.content[0].text
except AuthenticationError as exc:
raise SystemExit(f"401:检查 Key 与鉴权头,request-id={exc.request_id}") from exc
except NotFoundError as exc:
raise SystemExit(f"404:检查 Base URL 与模型名,request-id={exc.request_id}") from exc
except RateLimitError:
wait = min(2 ** attempt, 20) + random.random()
print(f"429:等待 {wait:.1f}s 后重试")
time.sleep(wait)
except (APITimeoutError, APIConnectionError):
wait = min(2 ** attempt, 10) + random.random()
print(f"超时或连接失败:等待 {wait:.1f}s 后重试")
time.sleep(wait)
except APIStatusError as exc:
if exc.status_code >= 500:
wait = min(2 ** attempt, 20) + random.random()
print(f"{exc.status_code}:等待 {wait:.1f}s 后重试")
time.sleep(wait)
continue
raise
raise RuntimeError("重试次数已用完,转降级或告警")
print(ask("只回复 OK"))
如果网关只接受 Bearer 鉴权,按客户端文档改用对应参数,或先用 curl 确认请求头。示例没有显式设置 max_retries,SDK 仍会默认重试,生产环境建议统一配置。
常见问题
401 一定是 Key 错了吗?
不一定。鉴权头不匹配、Base URL 指错环境、代理改写请求头,都会返回 401。先用同一个 Key 和 Base URL 直连测试,再检查客户端变量。
404 换了模型还是报,怎么办?
重点查 Base URL 路径。Claude Code 通常填根地址,客户端拼接 /v1/messages;填了带 /v1 的地址会变成双 /v1。其次确认模型名与网关列表一致。
429 等一会儿就一定恢复吗?
不一定。速率限制通常会恢复,但支出上限触发的 429 可能不带 retry-after,等待没有意义,需要调整限额或充值。先看错误类型和响应头再决定。
流式请求返回 200 后中断,算成功吗?
不算。流式响应可能在 200 之后通过 SSE 发送错误事件。客户端要解析事件流,确认收到正常结束事件,否则把结果标记为不完整并重试或告警。
重试次数设得越多越稳吗?
不是。重试只解决瞬时错误,次数过多会放大故障和成本。设置上限、指数退避和随机抖动,区分可重试与不可重试的错误;有副作用的操作先确认是否执行过再重发。
下一步
先在中商起航 AI 网关创建一个测试 Key,把 401、404、429 和超时各演练一次,再接入生产监控。模型可用性与计费以模型价格为准。
相关阅读:
