教程Claude Code系列第 4 / 21 篇

Claude API 的报错、限流和停止原因:每个状态码和 stop_reason 是什么意思,通过中转站时哪些不一样

调 Claude 的接口时,请求没成功是一回事,成功了但回答停得不对是另一回事。本文整理官方的十一个报错状态码、两种限额、七个停止原因和拒答的处理办法,并通过中转站用 Python SDK 把能触发的都触发了一遍:报错的类型名、限流的响应头、停止序列等好几处和官方文档不一样。

发布 · 约 13 分钟读完 · 经人工审核()· 本站的内容怎么来的

本站已实测,测试日期:2026-10-13。

本页目录(11 节)
  1. 一、先分清两件事
  2. 二、报错:十一个状态码
  3. 三、SDK 怎么把报错交给你
  4. 四、限额:两种,表现不一样
  5. 五、停止原因:七个值
  6. 六、拒答:它是 200,不是报错
  7. 七、通过中转站实测到的不一样
  8. 八、地区和 IP 地址
  9. 和 Claude Code 的关系
  10. 花费
  11. 这次实测没有覆盖到的

这篇教程解决一个问题:调 Claude 的接口,或者 Claude Code 替你调的时候,请求没成功、或者回答停在了半截,怎么从返回的东西里看出原因,下一步该做什么?

Claude Code 里看到的 API Error: 429、529 Overloaded 都出自这一套,所以不自己写代码的读者也用得上前半部分。

实测环境
日期 2026-10-13
版本 Anthropic Python SDK 1.13.0,Python 3.12.3
模型 Sonnet 5.5,个别地方用 Opus 5.5 对照
连接方式 通过酷站AI 中转站,不是直连官方

先说清楚这次实测的边界: 本站没有官方的 key,官方接口本身没有测。下面每一节先讲官方文档的规则,凡是写“实测”的,都是通过中转站看到的。两边不一样的地方集中在第七节。

一、先分清两件事

报错 停止原因
HTTP 状态码 4xx 或 5xx 200
意思 请求没处理成 请求处理成了,这是回答为什么在这里停下
在哪看 响应体里的 error 响应体里的 stop_reason
有没有内容 没有 有,可能不完整

很多“回答被截断”“工具没调完”的问题不是报错,是没看 stop_reason。

二、报错:十一个状态码

官方接口的报错都是这个形状:

{
  "type": "error",
  "error": { "type": "not_found_error", "message": "The requested resource could not be found." },
  "request_id": "req_011CSHoEeqs5C35K2UUqR7Fy"
}
状态码 error.type 意思 怎么办
400 invalid_request_error 请求的格式或内容有问题。用量到了你自己设的花费上限也是 400 看 message,改请求
401 authentication_error key 有问题:写错、被撤销、过期 换 key
402 billing_error 账单或付款信息有问题 去控制台看付款
403 permission_error 这把 key 没有权限用这个资源 看组织和工作区的设置
404 not_found_error 资源不存在 检查路径和 ID
409 conflict_error 和资源当前的状态冲突 解决冲突后重试
413 request_too_large 请求体太大。Messages API 的上限是 32 MB 减小请求
429 rate_limit_error 触发了限流,或者到了这一档的月度花费上限 见第四节
500 api_error Anthropic 内部出错 退避重试,一直不好就带上请求编号找支持
504 timeout_error 处理超时 长请求改用流式
529 overloaded_error 接口整体过载,所有用户都受影响 等一会儿重试

429 和 529 容易混:429 是你自己的额度到了,529 是大家的服务挤了。

每个响应都带一个请求编号,在 request-id 响应头里,报错时响应体里也有。找官方支持时要给这个。

文档还单独列了几种常见的 400,都和模型换代有关:

你发了什么 现在的结果
最后一条消息是 assistant(预填回答的开头) Claude 4.6 及之后的模型不支持,400
thinking 的 type 是 enabled Claude 4.7 及之后的模型不支持,改用 adaptive 加 effort
把 thinking 设成 disabled Opus 5.5 等模型思考永远开着,400。Sonnet 5.5 要改用 between_tools
把上一轮的 thinking 块改过、删过再发回去 400。带工具调用时,thinking 块要原样传回

三、SDK 怎么把报错交给你

用官方 SDK 时,报错不是一段 JSON,是一个异常,类名按状态码分:

import anthropic

client = anthropic.Anthropic()          # 地址和 key 从环境变量里取

try:
    msg = client.messages.create(
        model="claude-sonnet-5-5", max_tokens=1024,
        messages=[{"role": "user", "content": "你好"}],
    )
except anthropic.APIStatusError as e:   # 所有带状态码的报错的父类
    print(type(e).__name__, e.status_code)
    print(e.body)                       # 响应体里的 JSON

实测触发了三种:

怎么触发的 异常类 状态码
模型名写错 NotFoundError 404
messages 是空列表 BadRequestError 400
key 是错的 AuthenticationError 401

SDK 还替你做了三件事:

  • 自动重试。 连接错误、限流和 5xx 会按指数退避重试,响应里有 retry-after 就照它等。实测这个版本默认重试 2 次,用 max_retries 改,设成 0 就是不重试。
  • 超时。 实测默认的读超时是 600 秒。
  • 拦下太长的非流式请求。 非流式请求的 max_tokens 设到 128000,SDK 根本不发出去,直接抛异常:
ValueError:Streaming is required for operations that may take longer than 10 minutes.

原因是有些网络会掐掉长时间没有数据的连接。不需要逐段处理输出的话,可以让 SDK 替你把流读完,拿到的还是一个完整的消息对象:

with client.messages.stream(model="claude-sonnet-5-5", max_tokens=128000, messages=[...]) as stream:
    message = stream.get_final_message()

流式响应有一处特别:报错可能在已经返回 200 之后才来,以事件的形式出现在流里,不走上面的状态码那一套。

四、限额:两种,表现不一样

花费上限 速率限制
限的是什么 一个月最多花多少钱 一段时间里最多发多少请求、多少 token
到了之后 一直失败,到下个月 1 号 UTC 零点或者你升档 等一会儿就恢复
retry-after 头 没有 有

两种到了都是 429,类型都是 rate_limit_error。区分的办法:花费上限的那种,响应体里多一项:

"details": { "error_code": "enforced_spend_limit_reached" }

这种 429 重试没有用,SDK 的自动重试也一样失败。先看有没有 retry-after,没有就别重试了。

花费上限

组织按使用历史自动分档,每一档有月度上限:

档位 每月花费上限
Start 500 美元
Build 1,000 美元
Scale 200,000 美元
Custom 没有,和客户团队商定

新组织可能先在一个额度更低的评估档里待一段时间。

你也可以在控制台给自己设一个更低的上限。碰到自己设的上限时返回的是 400,不是 429,消息以 You have reached your specified API usage limits 开头。

速率限制

按模型分别算,量三样:每分钟请求数(RPM)、每分钟输入 token(ITPM)、每分钟输出 token(OTPM)。Sonnet 5.5 的标准额度:

档位 RPM ITPM OTPM
Start 1,000 2,000,000 400,000
Build 5,000 5,000,000 1,000,000
Scale 10,000 10,000,000 2,000,000

几条不看文档想不到的规则:

  • 用的是令牌桶。 额度持续回填,不是整点清零。每分钟 60 次可能被执行成每秒 1 次,短时间里猛发一阵照样会触发。
  • 从缓存读的输入不算进 ITPM。 对多数模型,只有没缓存的输入和写缓存的输入才算。缓存命中率 80% 时,同样的额度能处理五倍的输入。这是用提示缓存的另一个理由。
  • OTPM 只算真正生成的 token。 max_tokens 设多大不影响限流。
  • 用量突然猛增也会 429。 文档管这叫加速限制,办法是慢慢加量。

每个响应都带着一组头,告诉你现在的余量:

响应头 内容
retry-after 要等几秒才能重试
anthropic-ratelimit-requests-remaining 还能发几次请求
anthropic-ratelimit-input-tokens-remaining 还剩多少输入 token
anthropic-ratelimit-output-tokens-remaining 还剩多少输出 token

每一种还各有 -limit(上限)和 -reset(什么时候回满)两个头。

服务等级

请求有三种等级:标准(默认)、优先(Priority Tier)、批量。优先等级的容量承诺已经停止新购,只有已经签了合同的组织还在用。每个响应的 usage 里有一项 service_tier,写着这次请求走的是哪一种。实测拿到的是 standard。

五、停止原因:七个值

每个成功的响应都有 stop_reason:

值 什么时候出现 怎么办
end_turn 它自己说完了 直接用
max_tokens 到了你设的 max_tokens 调大,或者接着生成
stop_sequence 输出里出现了你指定的停止序列 看 stop_sequence 字段是哪一个
tool_use 它要调工具 执行工具,把结果传回去
pause_turn 服务端工具(比如网页搜索)的循环到了次数上限,默认 10 次 把这条回复原样传回去,让它接着做
refusal 它拒绝回答 见第六节
model_context_window_exceeded 回答把模型的上下文窗口占满了 当成被截断的回答处理

实测触发了前面几个里的三个:

--- max_tokens=5
    stop_reason=max_tokens  内容块=['text']  文字='长城是中国'  output_tokens=5
--- 带一个工具,问“上海现在天气怎么样?”
    stop_reason=tool_use  内容块=['tool_use']
--- 普通的一问一答
    stop_reason=end_turn

max_tokens 那次,回答停在了“长城是中国”五个字上,没有任何别的提示。不检查 stop_reason,你拿到的就是半句话。

流式时它出现的位置是固定的。实测的事件顺序:

message_start:stop_reason = None
message_delta:{"container": null, "stop_details": null, "stop_reason": "max_tokens", "stop_sequence": null}
事件顺序:message_start → content_block_start → content_block_delta → text → content_block_stop → message_delta → message_stop

开头的 message_start 里它是空的,要等到快结束的 message_delta 才有。顺序里的 text 是 SDK 自己加的便利事件,其余是接口发来的。

文档里另外几条值得记的:

  • 被 max_tokens 截断的回答如果停在一个不完整的工具调用上,只能调大 max_tokens 重发。
  • 偶尔会拿到一个空的 end_turn。 常见的原因是你在工具结果后面紧跟着加了一段文字,或者把它已经说完的回答原样又发了一遍。办法是工具结果后面不要加文字;确实要催它,另起一条用户消息。
  • tool_use 之后的那条用户消息里,只能放工具结果。

六、拒答:它是 200,不是报错

Fable 5.1、Fable 5、Opus 5.5、Opus 5、Sonnet 5.5、Haiku 5.5 这几个模型带着安全分类器,可能拒绝一个请求。拒绝时你拿到的是一个正常的 200 响应:

{
  "content": [],
  "stop_reason": "refusal",
  "stop_details": {
    "type": "refusal",
    "category": "cyber",
    "explanation": "This request was declined because it could enable cyber harm."
  }
}

category 说的是哪一类政策,五个取值里有三个即使一个字没输出也要收费:

category 意思 没输出时收不收费
cyber 可能助长网络攻击。正当的安全工作也可能触发 不收
bio 可能助长生物危害。正当的生命科学工作也可能触发 收
frontier_llm 可能帮助开发竞争的 AI 模型。正当的机器学习工作也可能触发 收
reasoning_extraction 要求模型把内部的推理过程写进回答里 收
general_harms 上面四类之外的使用政策范围 不收

category 和 explanation 也可能都是空的。写代码时按 stop_reason 判断,不要假定这两个字段一定有值。explanation 的文字不保证稳定,拿来显示可以,别去解析。

拒答可能发生在输出之前,也可能在流式输出到一半时。已经收到的那部分要当成不完整的,丢掉。

被拒了怎么办

多数情况下,同一个请求换一个模型就能答。三种做法:

你的情况 用什么
直连 Claude API,要最省事的 服务端回退:请求里加 fallbacks: "default",被拒时接口自己换到官方推荐的模型上重试,你只收到一个响应。目前是测试版,要带 beta 头
用官方 SDK,任何平台 SDK 的中间件:在客户端配一次,自动重试
自己发 HTTP,或者要自己控制重试 手动重试,配合回退抵扣

回退抵扣解决的是一个费用问题:提示缓存是按模型分开的,换了模型,之前缓存的那段对话要重新写一遍缓存,而写比读贵。拒答的响应里带一个抵扣令牌,重试时带上它,就按“这段对话一直在新模型上”来计费。前两种做法已经替你处理了,只有手动重试才需要管。

两个例外:

  • Haiku 5.5 没有服务端回退,也没有回退抵扣。 要用 SDK 中间件或者自己重试。
  • reasoning_extraction 没有推荐的回退模型,要改提示词。 它通常是因为提示里要求模型把思考过程写出来:一个要它先填的 <thinking> 段,JSON 输出里的 reasoning 字段,诸如此类。这类措辞可能藏在系统提示、skill 或者工具描述里。你仍然可以让它解释答案、给出依据;想看它怎么想的,读 thinking 块。

本站没有去故意触发拒答,这一节是按文档整理的。

七、通过中转站实测到的不一样

这是这次实测最主要的收获。同样的请求,通过中转站拿到的结果和官方文档写的有这些出入:

官方文档 实测(酷站AI,2026-10-13)
模型名写错 404,not_found_error 404,类型是 model_not_found,消息是中文
key 是错的 401,authentication_error 401,类型是 auth_failed
报错的响应体 顶层有 "type": "error" 和 request_id 有的有,有的没有;有的多一个 code 字段
请求编号 request-id 头,req_ 开头 没有这个头。有一个 x-request-id,是中转站自己的编号
限流的响应头 每个响应都有一组 anthropic-ratelimit- 头 一个也没有
不带 max_tokens 这是必填参数 503,带 retry-after: 60,类型是 billing_admission_failed
stop_sequences 命中时停下,stop_reason 是 stop_sequence 不生效。照常输出完,stop_reason 是 end_turn
最后一条是 assistant 400 200,模型接着预填的字往下写了
thinking 设成 disabled 400,提示改用 between_tools 200,正常回答
thinking 设成 between_tools Sonnet 5.5 支持 400,消息说本站暂不支持,改用 effort
多一个不认识的字段 这一组文档没有写 200,被忽略
不带 anthropic-version 头 这一组文档没有写 200,照常回答
路径写错 JSON 格式的 404 纯文本的 404 page not found

其中三处的原始输出:

--- 模型名写错
    异常类:NotFoundError  HTTP 404
    响应体:{"error": {"message": "模型 \"claude-does-not-exist\" 不存在,请检查模型名称;可在控制台“模型”页查看可用模型。", "type": "model_not_found"}, "type": "error"}

--- 不带 max_tokens,连发两次
    HTTP 503 retry-after=60 {"error": {"message": "计费用量记录暂不可用,本次请求未发送到上游", "type": "billing_admission_failed"}, "type": "error"}
    HTTP 503 retry-after=60 {"error": {…同上…}}

--- stop_sequences=['3'],让它从 1 数到 5
    HTTP 200 stop_reason=end_turn stop_sequence=None 文字='1, 2, 3, 4, 5'

停止序列这一条,Sonnet 5.5 和 Opus 5.5 各试了一次,用 SDK 和直接发 HTTP 各试了一次,中文和英文的序列都试了,结果相同。把 stop_sequences 故意写成错的类型(一个字符串、一个数字列表)也没有报错。

没有出入的部分:状态码本身是对的,所以 SDK 的异常类没有分错;end_turn、max_tokens、tool_use 三个停止原因正常;流式里 stop_reason 出现的位置正常;usage 里的字段齐全;Authorization: Bearer 和 x-api-key 两种带 key 的写法都认。

所以通过中转站写代码时

  1. 判断出了什么错,看 HTTP 状态码或者 SDK 的异常类,不要看 error.type。 类型名是中转站自己起的。
  2. max_tokens 一定要带。 漏了它拿到的是一个带 retry-after 的 503,SDK 会当成临时故障去重试,重试多少次都一样。
  3. 不要依赖 stop_sequences。 需要在某个标记处截断,拿到完整输出后自己截。
  4. 拿不到限流的余量。 没有那组响应头,要自己控制发送的速度,遇到 429 自己退避。
  5. 排查问题时记下 x-request-id。 找中转站查某一次请求,用的是这个编号。
  6. 在中转站上能跑通的请求,换到官方接口上可能被拒。 预填、thinking: disabled、多余的字段,官方那边都会是 400。

这些出入本站已经整理出复现步骤。它们是这一家、这一天的表现,别家可能不同,这一家以后也可能改。选中转站时可以照着这张表自己测一遍;辨别中转站的其他办法,见《通过中转站用 Claude Code》。

八、地区和 IP 地址

支持的地区。 官方列了一份可以使用 Claude API 的国家和地区名单。本站查了一下:名单里有日本、新加坡、台湾,没有中国大陆、香港和澳门。

IP 地址。 公司的防火墙要放行时用得上:

方向 地址段
你连 Anthropic(IPv4) 160.79.104.0/23
你连 Anthropic(IPv6) 2607:6bc0::/48
Anthropic 连你(比如它去调你的 MCP 服务器) 160.79.104.0/21

和 Claude Code 的关系

Claude Code 就是这套接口的一个客户端,它显示的报错是同一批:

  • API Error: 429:这把 key 的速率限制或花费上限到了。
  • Repeated 529 Overloaded errors:服务整体繁忙,不算在你的额度里。
  • 回答突然停了、工具调到一半:多半对应某个 stop_reason,Claude Code 自己会处理多数情况。

在 Claude Code 里怎么一步步查,见《Claude Code 常见报错怎么查》。

花费

这次一共发了四十来次请求,每次都只有几十个 token,花费没有单独统计。

这次实测没有覆盖到的

  • 官方接口没有测。 表里“官方文档”一列是照文档写的,本站没有官方的 key 可以对照。
  • 429、529、5xx、413、402、403、409 没有触发。 限流和过载要大量请求或者碰运气,本站没有去试。
  • 拒答没有触发,服务端回退、SDK 中间件、回退抵扣都是按文档整理的。
  • pause_turn 和 model_context_window_exceeded 没有触发。
  • 只测了一家中转站、一天、两个模型。
  • TypeScript 等其他语言的 SDK 没有测。

来源

通过 API 中转站使用这些模型?到 Veridrop 免费检测中转站给你的是不是它声称的模型,或者看看中转站排行榜前 100 名。

相关文章

  • Claude Code 的网络和数据:代理怎么配,它实际连了哪些地方,你的代码和对话去了哪教程 · Claude Code · 约 10 分钟

    本站在代理后面跑 Claude Code,记下它实际连的主机:即使模型请求走中转站,一句话的工夫它还连了五次 api.anthropic.com;设一个环境变量后只剩中转站。附代理配错的三种表现(非交互模式下会一声不吭地卡两分钟以上)、证书和防火墙要放行的地址,以及对话和代码存在哪、存多久、哪些会被发出去。

  • Claude Code 的设置文件:四个文件各管什么、谁盖过谁、怎么确认生效教程 · Claude Code · 约 11 分钟

    改了设置没反应,多半是写错了文件,或者被更高一层盖住了。本站实测了项目共享、项目本地和命令行三层的先后,权限规则跨文件合并,哪些值写在项目文件里不生效,以及设置写坏时的表现:多一个逗号整份文件作废,键名拼错则一声不吭。附 ~/.claude 目录里它自己存了哪些数据。

  • Claude Code 常见报错怎么查:连不上、401、模型不可用、配置不生效教程 · Claude Code · 约 15 分钟

    报错分三类:装不上、请求报错、配置不生效。本站用假地址和假 key 把常见的请求报错逐个复现,记下原文和原因。两个容易误判的:接口地址多写一级 /v1,报的是“模型有问题”;settings.json 写坏了,claude -p 照常运行、没有提示。附 claude doctor、--debug 的用法。

  • 通过中转站用 Claude Code:哪些功能和直连一样,哪些不一样,出了问题怎么判断是谁的教程 · Claude Code · 约 12 分钟

    Claude Code 官方有一份写给网关的兼容性说明:哪些请求头和字段必须原样转发,漏了会坏什么。本站对照这份说明,在一家中转站上把十几项功能实测了一遍:大部分正常,遇到过三处不一样的地方,其中子代理换模型后主会话报 400 的一处,中转站已经修好。附判断问题出在哪一方的办法。