工具大全
踩坑实录作者:Coocon2026年10月4日29 次阅读约 9 分钟阅读

Claude Code 429 怎么办:Request rejected (429) 原文、会重试多久、retry-after 超过 60 秒直接放弃(实测)

先回答你搜的问题

  • API Error: Request rejected (429) 是什么:后端(Anthropic 官方,或者你用的中转站 / 网关)说你请求太多了。· 后面那段是后端返回的原话,判断是谁限的流就看这一段。
  • 要不要手动重试:一般不用。Claude Code 已经自己重试了最多 10 次、大约 3 分钟,你看到报错时说明这 3 分钟里一直在被限流。
  • 一瞬间就报错、根本没等:后端给的 retry-after 超过了 60 秒,Claude Code 直接放弃了(实测阈值正好在 60 / 61 秒之间)。这种情况等一段时间再发就行,或者找中转站调大限额。
  • 交互模式下界面一直显示 Retrying in Ns · attempt N/10:这是正常的退避等待,不是卡死,可以按 Esc 中断。
  • 月度消费上限触发的 429:官方文档说这类 429 不带 retry-after,额度恢复前会一直失败。重试救不了,只能去控制台看额度。

问题背景

用 Claude Code 跑长任务,或者接的是国内中转站,时不时会看到这样一句:

API Error: Request rejected (429) · Number of request tokens has exceeded your per-minute rate limit

搜这句话的人通常想知道三件事:是谁在限流、Claude Code 自己会不会重试、要等多久。官方文档只说 SDK「会按指数退避重试,遇到 retry-after 头会遵守」,没说 Claude Code 具体重试几次、等多久,也没说 retry-after 很大时会怎样。

站内 上一篇 已经测过 429 的基本重试曲线,但留了几个空白:429 之后恢复成功的过程、交互模式下的显示、retry-after 取较大值时的行为、中转站的 429 长什么样。这篇专门把这些补齐。

问题分析

先确定 429 可能来自哪里,以及它们分别长什么样。下面都来自一手源:

来源 429 长什么样 出处
Anthropic 官方 API {"type":"error","error":{"type":"rate_limit_error","message":"…"}},通常带 retry-after 官方错误码文档
Anthropic 月度消费上限 同样是 rate_limit_error,但不带 retry-after,额度恢复前一直失败 同上,原文:A tier spend-cap 429 has no retry-after header and keeps failing until access resumes
new-api 按模型限流 OpenAI 风格:{"error":{"message":"您已达到请求数限制:N分钟内最多请求M次 (request id: …)","type":"new_api_error","code":""}} new-api 源码 middleware/model-rate-limit.go、middleware/utils.go(commit 1a4166d8e8)
new-api 全局限流 空 body,只有 Retry-After 头,值是整个限流窗口的秒数 同上 middleware/rate-limit.go 的 writeRateLimited
nginx limit_req 一段 HTML 错误页 <title>429 Too Many Requests</title> nginx 默认错误页
DeepSeek 文档只写了 429 - Rate Limit Reached,没给 body 格式 DeepSeek 错误码

另外,在 2.1.285 的二进制里能找到 anthropic-ratelimit-unified-status、anthropic-ratelimit-unified-reset 等一组响应头名,以及 Usage limit reached 等文案。这组头是订阅用户(Pro / Max)的用量限制,后面会验证:用 API key 接入时它们不生效。

技术方案与选型

方案 结论 理由
本地 stub 模拟后端 ✅ 采用 状态码、body、retry-after 都能精确控制;每个请求带毫秒时间戳记录下来;不花钱,不影响真实账号
用真实账号撞限流 ❌ 排除 429 很难稳定触发,retry-after 的值也控制不了;还会消耗真实额度,同一账号上的其他服务可能被连带限流
只读二进制里的字符串 ❌ 不能单独用 文案被编译拆成了碎片,拼不出完整的显示模板;能说明「有这句话」,说明不了「什么时候显示」

需要说清楚的一点:服务端返回什么是我们模拟的,Claude Code 客户端怎么反应(重试几次、等多久、显示什么)是真实的。 body 文案尽量照搬上表的一手源。

隔离做法和上一篇相同:

  • 每次运行用 env -i 清空环境,配一个全新的空 CLAUDE_CONFIG_DIR,不碰本机的登录态和会话记录。
  • ANTHROPIC_BASE_URL 指向 127.0.0.1 上的 stub,ANTHROPIC_API_KEY 用一把假 key。
  • HTTPS_PROXY 也指向 stub:所有 CONNECT 外连都会被记录并拒绝。本轮记到的外连目标有 api.anthropic.com、github.com、raw.githubusercontent.com、downloads.claude.ai、registry.npmmirror.com,全部被拦,没有一个请求到达真实服务。
  • -p 模式统一用 claude -p 'reply with exactly OK' --model haiku < /dev/null;交互模式在 tmux 里启动真实 TUI,每秒截一帧屏幕。

实测过程

本轮共 33 次 claude -p 运行加 3 个交互会话,每个 -p case 至少跑 2 次,报错文本、退出码、请求数全部一致。

1. 不同来源的 429,Claude Code 显示什么

设 CLAUDE_CODE_MAX_RETRIES=0 关掉重试,直接看最终报错(stdout 原文,exit 均为 1,stderr 均为 0 字节):

后端返回 Claude Code 显示
Anthropic 格式 rate_limit_error API Error: Request rejected (429) · Number of request tokens has exceeded your per-minute rate limit
new-api 按模型限流 API Error: Request rejected (429) · 您已达到请求数限制:1分钟内最多请求10次 (request id: 2026…)
new-api 全局限流(空 body) API Error: Request rejected (429) · status code (no body)
nginx HTML 错误页 API Error: Request rejected (429) · Too Many Requests
Anthropic 格式 + 订阅限流头 anthropic-ratelimit-unified-status: rejected 和第一行完全相同,订阅头被忽略

所以判断「谁限的流」看 · 后面:英文 rate limit 字样多半是官方或兼容官方格式的网关,中文提示是中转站,status code (no body) 是网关层面的全局限流,Too Many Requests 是前面的 nginx。

2. 会重试多久

默认设置下,429 一直不恢复(模拟月度上限那种不带 retry-after 的 429):

case stub 请求数 墙钟 相邻请求间隔(ms)
不带 retry-after,第 1 次运行 11 182.30 s 618, 1118, 2129, 4920, 9818, 16225, 35616, 35118, 36829, 39009
同上,第 2 次运行 11 176.41 s 536, 1093, 2371, 4760, 9361, 16311, 32934, 34650, 38356, 35746
带订阅限流头 × 2 次 11 / 11 175.94 / 176.52 s 同一条曲线

1 次原始请求加 10 次重试,间隔从 0.5 秒起逐次翻倍,从第 7 次起封顶在 32~40 秒,总共约 3 分钟。这和上一篇在 2.1.280 上测到的曲线一致,两个版本之间没有变化。

3. 中途恢复:完全无感

前 3 次返回 429,第 4 次返回正常:

case exit 墙钟 间隔(ms) stdout
429 带 retry-after: 1 ×3 → 正常 0 / 0 5.06 / 4.45 s 1024, 1015, 2187 / 1011, 1061, 2110 OK
429 不带 retry-after ×3 → 正常 0 / 0 4.73 / 4.23 s 513, 1225, 2129 / 573, 1260, 2108 OK

-p 模式下恢复后 stdout 只有 OK,stderr 是 0 字节,exit 0。脚本完全看不出中途被限流过,只是慢了几秒。

注意第一行的第 3 个间隔是 2.1 秒而不是 1 秒:retry-after: 1 时,实际等待看起来是「retry-after 和指数退避两者取大」。这是从读数推断的,没有在代码里确认。

4. retry-after 的 60 秒上限

这是本次最重要的发现。429 带不同的 retry-after,下一次返回正常:

retry-after 结果 stub 请求数 墙钟
10 ✅ 等满后恢复,exit 0 2 / 2 10.88 / 10.31 s(间隔 10018 / 10012 ms)
60 ✅ 等满后恢复,exit 0 2 / 2 60.87 / 60.31 s(间隔 60022 / 60012 ms)
61 ❌ 不重试,直接报错,exit 1 1 / 1 / 1 0.55 / 0.27 / 0.27 s
90、120、180、300、301、360 ❌ 同上 各 1 0.53~0.59 s
600 ❌ 同上 1 / 1 0.88 / 0.45 s

**retry-after ≤ 60 秒会老老实实等满,≥ 61 秒一次都不重试。**交互模式下也一样,retry-after: 61 时界面上 0 秒就显示了最终报错(Churned for 0s)。

这对用中转站的人影响很大:new-api 的全局限流会把整个窗口的秒数放进 Retry-After,窗口一旦超过 1 分钟,Claude Code 就会立刻放弃,看起来像「一点就报错,根本没重试」。

我在二进制里查了所有带 RETRY 的环境变量名,跟重试有关的只有 CLAUDE_CODE_MAX_RETRIES(控制次数),没找到能调这个 60 秒上限的开关。

5. 交互模式:界面长什么样

在 tmux 里启动真实的交互式会话,发一句话,后端一直返回 429(retry-after: 1),每秒截一帧。按时间顺序,提示行依次是:

✻ API error · Retrying in 1s · attempt 2/10
✻ 429 Number of request tokens has exceeded your per-minute rate limit · Retrying in 3s · attempt 3/10
✻ 429 Number of request tokens has exceeded your per-minute rate limit · Retrying in 9s · attempt 5/10
✻ 429 Number of request tokens has exceeded your per-minute rate limit · Retrying in 39s · attempt 7/10
…
⏺ API Error: Request rejected (429) · Number of request tokens has exceeded your per-minute rate limit
✻ Brewed for 3m 3s
  • 第 2 次尝试只显示笼统的 API error,从第 3 次起才带上 429 和后端原话。
  • Retrying in Ns 每秒刷新倒计时,所以「界面一直在动」不是卡死。
  • 最终报错之后,会话不会退出,可以直接再发一句。

另一个会话里,前几次返回 429,之后恢复正常:界面上只闪过一下 API error · Retrying in 2s · attempt 2/10,然后正常输出 OK,对话记录里不留任何报错痕迹。

6. 交互模式下,一句话会发 2 个请求

看 stub 日志才发现:交互模式下每发一句话,会同时发出 2 个 /v1/messages 请求。一个带 28 个工具定义,是主请求;另一个 0 个工具,内容以 <session> 开头,是一个附带的侧请求。两路各自独立重试。

时间(s) 主请求 侧请求
6.08 / 6.09 429 429
8.09 / 8.10 429 429
10.10 / 10.10 正常 正常

对按「每分钟请求数」限流的中转站来说,交互模式消耗的请求数是你以为的 2 倍;被限流后两路同时重试,也是 2 倍。-p 模式只发 1 个请求(上面所有 -p case 的请求数都能对上)。

实践效果

**1. 先看 · 后面是谁说的。**英文 rate limit 是官方或兼容网关;中文「您已达到请求数限制」是中转站,去中转站后台调限额或换分组;status code (no body) 是网关的全局限流;Too Many Requests 是前置 nginx。

**2. 秒报错、没等待,多半是 retry-after 超过了 60 秒。**可以用下面这条命令看后端到底返回了多大的 retry-after(地址和 key 取自你给 Claude Code 配的环境变量,模型名换成你的后端支持的):

curl -s -o /dev/null -D - "$ANTHROPIC_BASE_URL/v1/messages" \
  -H "x-api-key: $ANTHROPIC_API_KEY" -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-haiku-4-5","max_tokens":8,"messages":[{"role":"user","content":"hi"}]}' \
  | grep -iE '^HTTP|retry-after'

注意这条命令本身也会消耗一次请求额度。如果看到 retry-after 大于 60,等这么久再发,或者让中转站把限流窗口调小。

**3. 脚本 / CI 里:**429 能在 3 分钟内恢复的话,-p 的输出和退出码完全正常,不需要额外处理。如果想快速失败(比如健康检查),用 CLAUDE_CODE_MAX_RETRIES=0。长任务不要设成 0,429 本来就该退避重试。

**4. 中转站运营方:**想让 Claude Code 自动等待,Retry-After 不要超过 60;超过就会被当成「不值得等」直接失败。另外,交互模式下每句话会打 2 个请求,按请求数限流时要算进去。

**5. 月度消费上限:**官方的这类 429 不带 retry-after,Claude Code 会白白重试 3 分钟后报错。重试解决不了,去 Console 看额度或调整 spend limit。

本轮全部请求都打在本地 stub 上,真实 API 花费为 0。

踩坑

  • **看门狗的 sleep 进程占住了管道。**runner 用一个后台子 shell 做超时看门狗,正常结束时 kill 掉子 shell,但里面的 sleep 900 成了孤儿进程,继续占着 stdout。结果是写文件时没有问题,接 | grep 时就卡 15 分钟。改成在子 shell 里 exec >/dev/null 并用 trap 带走 sleep 后解决。
  • **交互模式下 429 序列被两路请求瓜分。**第一次跑恢复 case 时,按「前 4 次返回 429」设计,结果比预期快了一半,看日志才发现主请求和侧请求各吃掉了 2 次。上面第 6 节就是这么来的。
  • 二进制里的文案是碎片。Usage limit reached、Retrying in、too far out to wait for 都能搜到,但拼不出完整句子,最终以实测截屏为准。

未验证清单:真实 Anthropic 后端的 429 body 原文(本文用的是上一篇沿用的文案);DeepSeek 429 的 body 格式(文档未给出);OAuth 订阅登录(Pro / Max)下的用量限制界面(本文只测了 API key 模式,订阅头在该模式下被忽略);retry-after 在 5960 秒之间的边界抖动;retry-after 用 HTTP 日期格式而不是秒数时的行为。每个 -p case 只跑了 23 次。

相关阅读

这类实测,每周六汇总一封

订阅码农早餐:每天 8:00 一封 AI 编程早报,每周六另附本周 Claude Code / Codex / 本地模型的实测和踩坑汇总。

相关文章

Claude Code 上下文太长怎么办:Prompt is too long 会自动压缩,中转站 / DeepSeek 的 maximum context length 却不会(实测)

Claude Code 靠报错文案判断「上下文太长」:后端说 prompt is too long 或 input is too long for requested model,它会自动压缩对话后重发,用户无感;DeepSeek 和 OpenAI 风格中转返回的 This model's maximum context length is …,它不认识,直接报 API Error: 400,每轮都失败。手动 /compact 有效;更好的办法是用 CLAUDE_CODE_MAX_CONTEXT_TOKENS(非 claude- 模型 ID)或 CLAUDE_CODE_AUTO_COMPACT_WINDOW(claude- 模型 ID)告诉它真实上限,让它提前压缩。Claude Code 2.1.285 + 本地 stub 实测。

claude-codedeepseek+6
pitfalls2026年10月5日8 min
29

Claude Code 一直卡住、转圈没反应怎么办:后端不回时它要等 6 分钟,重试满 10 次可能卡一个多小时(实测)

Claude Code 转圈不动、或者停在 Retrying in 0s,多半是后端没有回数据。实测 2.1.285(API key + ANTHROPIC_BASE_URL):后端不回响应头时每次等 6 分钟(360 秒)才判超时,把 API_TIMEOUT_MS 调到 60 万、90 万也不变,只能调小;默认重试 10 次,总共可能卡一个多小时。中转站如果把回复缓冲到生成完才返回,超过 6 分钟的回复永远拿不到。按 Esc 可以随时中断。全部在本地 stub 上实测。

claude-code中转站+6
pitfalls2026年10月5日10 min
21
Claude Code MCP 显示 Connected 却 0 个工具:Invalid result for tools/list(ttlMs / cacheScope)实测与修法

Claude Code MCP 显示 Connected 却 0 个工具:Invalid result for tools/list(ttlMs / cacheScope)实测与修法

MCP server 显示已连接、工具数却是 0,日志里是 Invalid result for tools/list,ttlMs 与 cacheScope 校验失败。用自写 stub 在 Claude Code 2.1.280 / 2.1.285 / 2.1.288 上复现:根因不是「多了未知字段被严格校验拒掉」,而是 server 协商到 MCP 2026-07-28 后漏了这一版的必填字段(resultType、ttlMs、cacheScope),多加未知字段反而能正常通过。stdio 是否走新协议由一个默认关闭的远程开关决定,所以同一个版本有人中招、有人没事;2.1.280 打开协商后同样失败。用户侧设 MCP_PROTOCOL_NEGOTIATION=legacy(settings.json 的 env 也行)立即恢复,server 侧补上三个字段即可。

mcpclaude-code+4
pitfalls2026年10月3日7 min
27
Claude Code 安装失败实测:npm EACCES、镜像卡 600 秒、Node 20 静默装旧版、install.sh 返回地区拦截页、原生安装器顺手卸掉 npm 版——15 条报错原文与解法

Claude Code 安装失败实测:npm EACCES、镜像卡 600 秒、Node 20 静默装旧版、install.sh 返回地区拦截页、原生安装器顺手卸掉 npm 版——15 条报错原文与解法

在 macOS 上把 claude code 安装的失败面逐个真实复现,共 15 条报错原文,全部带墙钟和 exit code。npm 全局装到 /usr/local:EACCES,exit 243。cache 目录只是 0555,npm 却报 root-owned 并建议 sudo chown。本机 npmmirror 两次分别用了 147 秒、超过 600 秒,官方源两次都在 11–12 秒(仅 2 个样本)。Node 20 不钉版本号会静默装到 2.1.197,没有任何警告。境内直连 claude.ai/install.sh 时 curl exit 0,拿到的却是一张 447KB 的地区拦截页 HTML。原生安装器会调用 npm uninstall -g,把已有的 npm 版删掉,终端里不提示——本次实测真的删掉了本机的全局安装。

claude-codenodejs+6
pitfalls2026年9月29日11 min
141