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。

按顺序排查:

  1. 确认协议:Claude Code 用 Anthropic Messages,不是 OpenAI Chat Completions。
  2. 检查 Base URL 是否多了或少了 /v1。Claude Code 一般填根地址;OpenAI 兼容客户端一般填带 /v1 的地址。
  3. 检查末尾斜杠和大小写,避免双斜杠或路径被截断。
  4. 到模型价格复制当前模型名;网关别名可能和官方名称不同。
  5. 用最小请求测试,排除代理和客户端缓存。

错误消息是 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。原因不是模型坏了,而是输入加输出的预算超过了上下文窗口。

处理顺序:

  1. 请求前用 count_tokens 量化输入,不要凭字数猜。
  2. 裁剪最早的历史,只保留 system、最近几轮和摘要。
  3. 文档先检索召回相关片段,不要整库放入。
  4. 长文档按章节拆分,分段处理后再合并。
  5. 压缩工具输出,只返回必要字段。
  6. 给输出留空间。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。

七、日志与支持清单

排查时不要只留一句“报错了”。按下面清单收集信息:

  1. 发生时间、时区、持续时长。
  2. claude --version 和操作系统。
  3. Base URL(保留域名,不带完整 Key)。
  4. 模型名、是否流式、请求耗时和重试次数。
  5. HTTP 状态码、错误类型和完整错误消息。
  6. request-id,响应头和响应体里都可能有。
  7. 影响范围:单人、单网络、单项目还是全团队。
  8. 最小复现:一条 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 和超时各演练一次,再接入生产监控。模型可用性与计费以模型价格为准。

相关阅读: