529 overloaded — 它有兩條到達路徑,只有一條會被自動重試
- 先分清它是怎麼來的:HTTP 529 已經被自動退避重試過了;流裡的
overloaded_error走的是另一條路,標準重試機制管不到它——「跑一半突然斷、一次沒重試」就是這一種。 - 529 不是 429。529 是服務整體飽和,不計入你的配額,你這邊沒有任何槓桿——併發、快取、檔位一個都不管用。
- 能縮短等待的只有兩件事:換一個同級模型繼續幹活,或在無人值守場景裡讓客戶端一直重試下去。
同一個 529,有人看到的是重試了十次才放棄,有人看到的是一次都沒重試就斷在回答中間。這不是隨機,也不是 bug——它是兩條到達路徑的差別。作為 HTTP 狀態碼返回的 529 走標準重試通道;而流式請求早就先返回了 200,過載只能作為流裡的一個事件送達,官方文件明確寫著這種情況下錯誤處理不走標準機制。搞清楚你手上是哪一種,比問「該等多久」有用得多。
你看到的報錯
API Error: 529 {"type":"error","error":{"type":"overloaded_error","message":"Overloaded"}}
API Error: Repeated 529 Overloaded errors. The API is at capacity — this is usually temporary. Try again in a moment. If it persists, check https://status.claude.com.
✻ API Error · Retrying in 8s · attempt 3/10
529 Overloaded
model overloaded · 模型過載,請稍後重試
還有一種,它不長這個樣子,而且正是它最容易被誤判成「網路斷了」:
event: error
data: {"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}
兩條到達路徑:同一個錯誤,不同的命運
| HTTP 529 — 請求還沒開始就被拒 | 流裡的 overloaded_error — 回答到一半 | |
|---|---|---|
| HTTP 狀態碼 | 529 | 200 — 響應頭早就發出去了 |
| 錯誤型別 | overloaded_error | overloaded_error — 完全一樣 |
| 怎麼送達 | 響應體 JSON | SSE 流裡的一個 event: error |
| 走標準重試嗎 | 走。官方 SDK 預設退避重試 2 次;Claude Code 預設最多 10 次 | 不走。官方文件原話:這種情況下錯誤處理不遵循標準機制 |
| 你看到它時 | 重試預算已經用完了 | 可能一次都沒重試過 |
| 典型體感 | 轉圈很久,然後報錯 | 字打到一半停住,像是斷網 |
| 已經產生的輸出 | 沒有 | 已經花掉了,而且那半截回答通常留不下來 |
error 事件。
529 和 429:共用「你被拒了」的體感,其餘毫無共同點
| 529 overloaded | 429 rate limit | |
|---|---|---|
| 誰的問題 | 服務整體飽和,影響所有人 | 你的組織越過了某條線 |
| 計入你的配額嗎 | 不計入 | 就是配額本身 |
有 retry-after 嗎 | 不保證有 | 普通限流有;配額耗盡沒有 |
| 你手上的槓桿 | 沒有。降併發、開快取、提檔位,全都不影響它 | 併發、快取、檔位都有效 |
| 什麼時候好 | 上游容量緩過來時 | 限流幾秒到幾分鐘;配額到重置時間 |
| 該做什麼 | 等,或換模型,或讓它一直重試 | 見 429 排查 |
有一個反直覺的方向值得單獨點出來,因為它會把人引到完全錯誤的一頁上去:如果你剛剛把用量陡然拉高,然後開始收到錯誤,那更可能是 429 而不是 529。官方文件在 529 的說明裡專門補了這條提示——用量急劇上升會撞上加速度限制,回的是 429。所以「我加量了然後就過載了」這句話裡,「過載」兩個字多半是記錯的:去看狀態碼,別看體感。
按這個順序排查
1 · 先確認它到底是不是 529#
「過載」是個很容易被套用到任何一次失敗上的詞。先把狀態碼和錯誤型別看清楚,因為後面每一步都建立在這個判斷上。
# <模型 id>:從 https://api.9coding.com/v1/models 裡複製一個
curl -sS -D - -o /dev/null https://api.9coding.com/v1/messages \
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
-H "content-type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{"model":"<模型 id>","max_tokens":16,"messages":[{"role":"user","content":"hi"}]}' \
| grep -iE 'http/|retry-after|request-id'
回的是 529 才是本頁說的事。回 401 看 401 排查,回 429 看 429 排查,什麼都回不了、連不上看 連線錯誤。
2 · 別在自動重試之上再疊一層手動重試#
HTTP 529 在冒到你眼前之前,已經被退避重試過了。你再按一次回車,是在重跑一個剛剛被證偽過若干次的假設。
先分清螢幕上的兩種狀態:帶嘗試次數的倒計時(形如 Retrying in 8s · attempt 3/10)說明它正在幹活,別動它;沒有倒計時、直接列印出來的報錯才是重試預算用完之後的終態。
3 · 如果它斷在回答中間,那是另一條路徑,需要另一種處理#
字打到一半停住、沒有倒計時、也沒有明顯報錯——這一類多半是流裡的 overloaded_error,而不是 HTTP 529。它的特徵很好認:已經輸出了一部分,然後戛然而止。
在互動式使用裡,這一類只能自己重發。在你自己寫的整合裡,它需要顯式處理:只判斷響應狀態碼的程式碼看不見它,因為狀態碼是 200。同時要注意,與之體感幾乎一樣、但成因完全不同的還有代理空閒超時掐斷長連線——判別方法見 流式回答中途斷掉:讓它輸出短一點,如果短回答正常、長回答必斷,那是超時不是過載。
4 · 換一個同級模型,是唯一能立刻見效的動作#
529 是容量事件,而容量是按模型緊張的——同一時刻,另一個同級模型往往是通的。這是本頁唯一一個不靠等待就能恢復幹活的辦法。
/model
會話不會丟,切完繼續往下幹即可。可選的模型 id 從 模型列表拿,或直接讀 /v1/models。
5 · 無人值守場景要改的是設定,不是心態#
CI 任務和長時間自主執行的會話裡,跑到一半失敗的代價遠大於等待。Claude Code 為此提供了一個開關,按官方錯誤參考,它會讓容量類錯誤一直重試下去,而不是在預設預算用完後失敗:
export CLAUDE_CODE_RETRY_WATCHDOG=1
它有一條必須知道的邊界:對寫明瞭消費上限或額度耗盡的 429,它仍然立刻失敗——因為對那類錯誤無限重試,只是一種更慢的失敗方式。相關的還有 CLAUDE_CODE_MAX_RETRIES(預設 10)和 API_TIMEOUT_MS。這幾項的預設值、上限、以及它們之間的相互作用在版本之間都變過,請按你正在跑的版本查環境變數參考。
6 · 把等待變成可觀測的,而不是反覆試#
529 沒有 retry-after 那樣可讀的契約頭告訴你還要多久,所以「再試一次」是一種沒有資訊量的動作。能查的是服務狀態:先看 狀態頁;直連 Anthropic 時官方報錯文案會直接指向它自己的狀態頁,走其他端點時則指向報錯裡寫明的那個主機。
要報障就帶上 request id——每一次響應都有 request-id 頭,報錯體裡也帶同一個值。9Coding 的報錯響應裡形如 (request id: 2026...)。這個 id 加上時間戳、模型名和完整報錯文字,才能把那一次呼叫查出來;只說「過載了」沒法排查。
什麼時候這不是你的問題
下面幾條同時成立,指向的就是上游容量事件,你這邊再怎麼調都沒用:
- 同一時間段裡,指向同一個端點的其他客戶端也在失敗,
- 它是在你的工作負載沒有任何變化的情況下開始的,
- 你什麼都沒改,它自己就恢復了,
- 換一個同級模型立刻就通。
反過來,如果只有你一個客戶端在失敗、而且是在你剛剛改了什麼之後開始的,那大機率不是 529——回到第 1 步把狀態碼看清楚。
相關報錯
- 429 Too Many Requests — 你這邊越線了,而且你手上有槓桿
- 流式回答中途斷掉 — 體感一樣,成因是超時不是過載
- Connection error — 連都沒連上,那是更靠前的一層
- 全部報錯速查 — 排查手冊總表