API 檢查了你送回的 thinking 區塊簽章,但驗證失敗:簽章可能遭到截斷、修改或以空值送回,或該區塊從未由 Claude 簽署——或者在 Claude Fable 5.1 和 Claude Opus 5.5 中,對話較早的內容發生了變更。每次重新傳送相同歷史記錄都會以相同方式失敗。找出破壞它的原因,然後只對該對話移除 thinking 區塊一次並繼續——你失去的是模型先前的推理,而不是對話。
錯誤
// Through Kunavo: the upstream message as it reaches you, typed as Anthropic
// types a 400; no request_id field, the upstream's own id is appended instead:
{"type":"error","error":{"type":"invalid_request_error","message":"messages.1.content.0: Invalid `signature` in `thinking` block (request id: …)"}}
// (the message path, any masking of it and the appended request id vary by upstream)
// From Anthropic's API directly:
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "messages.1.content.0: Invalid `signature` in `thinking` block"
},
"request_id": "req_011C..."
}
// messages.{i}.content.{j}: i = position in messages[], j = block index. Both vary.
// An upstream can mask that path (***.***) and append its own request id, as above.
// Claude Code prints the body after "API Error: 400".
// On Claude Fable 5.1 and Claude Opus 5.5 the message can continue:
// "... The block is bound to a different conversation. Remove the block, or set
// `thinking.block_binding.prefix_mismatch_behavior` to "drop_block"."原因與解決方法一覽
| 原因 | 解決方法 |
|---|---|
| 簽章在送回前遭到截斷、清空或編輯 | 依原樣儲存並重播每個區塊。讓 SDK 組合串流回合,以免遺失 signature_delta。 |
| 該區塊從未由 Claude 簽署 | Anthropic 相容 URL 背後的非 Claude 模型,或自行寫入簽章的代理伺服器。將這些回合以文字和 tool_use 傳回。 |
| 你在對話中途切換了基礎 URL、帳戶或登入狀態 | Claude Code 2.1.152+ 會在模型或登入切換後移除過時簽章。在你自己的程式碼中,如果切換後的第一個請求失敗,請移除 thinking 一次。 |
| 「該區塊繫結至不同的對話」(Fable 5.1、Opus 5.5) | 系統提示、工具或較早的訊息發生了變更。保持歷史記錄只追加不修改,或選擇 drop_block(需要 beta 標頭)。 |
| 代理伺服器或閘道在傳送途中重寫了歷史記錄 | 這些重寫會被視為你的編輯。直接對 API 重現,以確認或排除這項因素。 |
查看哪項檢查失敗
錯誤文字會告訴你原因。訊息停在「Invalid `signature` in `thinking` block」表示簽章本身未通過驗證:Anthropic 列出的原因包括遭到截斷、修改或以空值送回(https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting,截至 2026 年 9 月),其 preserved-thinking 頁面則稱這是遭竄改或無法解密的簽章,且必定回傳 400。被遮罩成 ***.***.content.0 的路徑或由閘道附加的請求 ID 都不會改變這一點;關鍵在於後面是否接著出現描述對話的句子。在 Claude Fable 5.1 和 Claude Opus 5.5 中,相同文字可能接著出現「The block is bound to a different conversation」——這表示該區塊繫結至不同的對話,是不同的檢查,於最後一步說明。第三種訊息「blocks in the latest assistant message cannot be modified」表示最新的 assistant 回合遭到編輯、過濾、重新排序或重建;編輯 thinking 文字會產生這項錯誤,而不是簽章錯誤。重試相同本文不會清除任何一種錯誤。
Invalid `signature` in `thinking` block
-> the signature did not verify: truncated, altered, empty, or not Claude's
Invalid `signature` in `thinking` block. The block is bound to a different conversation. ...
-> Fable 5.1 / Opus 5.5: system, tools or an earlier message changed after the block was made
`thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified
-> the newest assistant turn was edited, filtered, reordered or rebuilt before it was sent back將 assistant 回合依原樣送回
每個 thinking 區塊都帶有簽章——完整推理的加密副本——API 會用它來驗證該區塊是由 Claude 產生的(https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-encryption)。原封不動地追加回應的內容清單:thinking、redacted_thinking 和 tool_use 區塊,包括文字為空的 thinking 區塊;這是較新模型的預設顯示方式。使用串流時,簽章會在區塊關閉前,以單一 signature_delta 抵達;因此手動撰寫的累加器若漏掉它,就會儲存空簽章,而送回空簽章的區塊會失敗。Anthropic 建議讓 SDK 組合訊息。JSON 鍵的順序和空白不重要——值才重要。
import anthropic
client = anthropic.Anthropic(base_url="https://api.kunavo.com", api_key="sk-kn-...")
tools = [{
"name": "get_weather",
"description": "Current weather for a city.",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
}]
messages = [{"role": "user", "content": "What's the weather in Paris?"}]
with client.messages.stream(
model="claude-sonnet-4-6",
max_tokens=16000,
thinking={"type": "adaptive"},
tools=tools,
messages=messages,
) as stream:
final = stream.get_final_message() # signature_delta already applied
# Append the content list untouched: thinking, redacted_thinking, tool_use.
messages.append({"role": "assistant", "content": final.content})
# Not this: a store that keeps the text but not the signature replays
# {"type": "thinking", "thinking": "...", "signature": ""} -> this 400.不要將其他後端的 thinking 放入 Claude 歷史記錄
根據 Anthropic 文件,在其自身 API 上切換 Claude 模型本身不應觸發此錯誤:文件要求你切換時繼續傳送這些區塊,新模型無法讀取的區塊會被丟棄而不產生錯誤,並說明簽章可在 Claude API、Amazon Bedrock 和 Google Cloud 之間攜帶(https://platform.claude.com/docs/en/build-with-claude/thinking,截至 2026 年 9 月)。它無法驗證的是 Claude 從未簽署的區塊。公開報告涉及曾經通過其他後端的歷史記錄:一個在 GLM 後端執行、之後返回 Anthropic 的 Claude Code 工作階段(github.com/anthropics/claude-code/issues/21726);代理伺服器將 Gemini 回合偽裝成帶有自有簽章的 Claude thinking 區塊(github.com/router-for-me/CLIProxyAPI/issues/1584);以及一個在工作階段中途切換到另一把金鑰、之後再切回的 Claude Code 工作階段(github.com/lbjlaq/Antigravity-Manager/issues/388)。對於非 Claude 模型產生的回合,Anthropic 的建議是僅以文字和 tool_use 內容送回該模型的輸出。
def as_foreign_turn(content: list[dict]) -> list[dict]:
"""A turn a non-Claude model produced: keep what it said and did,
never its thinking blocks, which Claude cannot verify."""
return [b for b in content if b["type"] in ("text", "tool_use")]復原已經失敗的對話
只從儲存的歷史記錄中移除 thinking 和 redacted_thinking 區塊一次——移除全部最簡單;對於「繫結至不同的對話」變體,Anthropic 指定的最低要求是移除點名的區塊及其後的每個區塊——其他區塊都維持原位,儲存該歷史記錄並繼續。Anthropic 將此列為無法再重播的已儲存工作階段之復原方式(https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#faq);簽章無法驗證時,唯一其他出路是依原樣重播該區塊,前提是你仍保有它。Claude Code 在 API 拒絕簽章時會自行移除較早的 thinking。移除區塊並繼續後,不要將它們放回:在 Fable 5.1 中,已移除又放回的區塊會使它被移除期間產生的 thinking 失效。模型會在沒有先前推理的情況下回答,從那裡開始的新 thinking 有效。在 Claude Code 中,2.1.152(2026 年 5 月 27 日,https://code.claude.com/docs/en/changelog)會在模型或登入切換後移除過時簽章,其閘道指南則表示在簽章拒絕後會不帶較早的 thinking 重試——但該重試是依上游錯誤文字判斷,若閘道以自己的封裝包裹錯誤,就可能導致它失效(https://code.claude.com/docs/en/llm-gateway-protocol#automatic-retry-and-error-forwarding)。
THINKING = {"thinking", "redacted_thinking"}
def block_type(b) -> str:
return b["type"] if isinstance(b, dict) else b.type # dicts or SDK objects
def strip_thinking(messages: list[dict]) -> list[dict]:
"""One-time recovery: drop every thinking block, keep everything else."""
out = []
for m in messages:
content = m["content"]
if m["role"] == "assistant" and isinstance(content, list):
kept = [b for b in content if block_type(b) not in THINKING]
content = kept or [{"type": "text", "text": "(no visible reply)"}] # keep the turn non-empty
out.append({**m, "content": content})
return out
messages = strip_thinking(messages) # save this version; never re-add the blocks在 Fable 5.1 中,保持前綴固定——或選擇 drop_block
「Bound to a different conversation」(「繫結至不同的對話」)是 preserved-thinking 檢查:在 Claude Fable 5.1 和 Claude Opus 5.5 中,重播的區塊只有在系統提示、工具及所有較早訊息都未變更時才有效。對於 2026 年 8 月 31 日或之後建立的帳戶,Anthropic 預設強制執行此規則(https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#enforcement);在閘道後方,該帳戶並不屬於你,因此請假設此規則已啟用。在工作階段中保持系統提示和工具固定,並採用追加而非編輯。為了在找出導致問題的編輯期間維持請求成功,請傳送 thinking-binding-controls-2026-08-01 beta 標頭,並將 prefix_mismatch_behavior 設為 drop_block;沒有該標頭時,該欄位本身會因「block_binding: Extra inputs are not permitted」而遭拒絕(https://platform.claude.com/docs/en/api/errors)。
# Anthropic's API directly. The field needs the beta header; Kunavo forwards it (see below).
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: thinking-binding-controls-2026-08-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-fable-5-1",
"max_tokens": 16000,
"thinking": {
"type": "adaptive",
"block_binding": {"prefix_mismatch_behavior": "drop_block"}
},
"messages": [{"role": "user", "content": "..."}]
}'如果你透過 Kunavo 呼叫
Kunavo 會依原樣透傳經由 /v1/messages 傳送的 thinking 和 redacted_thinking 區塊,包括簽章和資料——唯一的請求變更是模型 ID,以及在拒絕這些參數的模型上移除 temperature、top_p 和 top_k——並依上游傳送的內容回傳回應本文,無論是否使用串流。截至 2026 年 9 月,每個 Claude 模型都透過單一上游通道提供服務,沒有備援通道,因此 Kunavo 的路由不會在供應商之間移動對話,400 也絕不會在其他地方重試。我們尚未測試在 Anthropic 直連與 Kunavo 之間移動對話,因此預期此類切換後的第一個請求需要移除 thinking。自 2026 年 9 月 24 日起,Kunavo 會轉送 thinking-binding-controls-2026-08-01 beta;當天的測試中,提供 Claude 的通道在有無該標頭的情況下都接受 Claude Fable 5.1 的 block_binding,我們也未見它移除任何區塊。拒絕會以 HTTP 400、類型為 invalid_request_error 抵達,不含 request_id 欄位,並攜帶上游的訊息文字——其中可能遮蔽 messages.N 路徑,並以上游自己的請求 ID 結尾——因此請依狀態和「Invalid `signature` in `thinking` block」這些文字進行比對。Claude Code 的自動移除並重試機制依據該文字判斷:Claude Code 2.1.280 指向一台以此封裝回應的測試伺服器時,移除了 thinking 區塊並重試。我們尚未透過 Kunavo 觸發此錯誤,因此若工作階段仍在每個回合都失敗,請開始新的工作階段。失敗的請求不會計費。 原生端點會原封不動透傳的內容列於 Messages API 參考文件.
常見問題
「Invalid `signature` in `thinking` block」是什麼意思?
API 無法驗證你送回的 thinking 區塊。每個 thinking 區塊都帶有簽章——Claude 推理的加密副本——當簽章遭到截斷、修改或以空值送回,或該區塊從未由 Claude 簽署時,檢查就會失敗。這是 400,而非暫時性錯誤:相同的請求每次都會失敗。
思考區塊簽章會過期嗎?
Anthropic 的文件沒有提到過期時間。在 anthropic-sdk-python 追蹤器(2026 年 8 月,issue #1598)中,一個 GitHub 標示為貢獻者的帳號回覆說不會,而且當送達 API 的區塊與先前回傳的區塊不一致時,檢查就會失敗——這是 issue 留言,不是文件。如果先前能正常運作的已儲存工作階段現在失敗,請檢查儲存的區塊或其傳遞路徑可能發生了哪些變化:您的儲存層、代理伺服器,或後端切換。
我可以直接刪除思考區塊後繼續嗎?
可以。Anthropic 將此列為無法重播的已儲存工作階段之復原方式,而 Claude Code 在簽章遭拒時也會自行移除較早的思考。移除 thinking 和 redacted_thinking 區塊——全部移除最簡單——保留其他區塊,然後重試一次。模型會失去先前的推理,而不是對話;在沒有工具使用的情況下,Anthropic 的文件本來就允許省略先前回合的思考。
為什麼切換模型或供應商後會發生?
Anthropic 的文件表示,透過其 API 在 Claude 模型之間切換時,新模型無法讀取的區塊會被丟棄,且不會顯示錯誤;簽章則可跨 Claude API、Amazon Bedrock 與 Google Cloud 使用。Claude Code 仍曾需要修復在模型或登入切換後卡在過時簽章的工作階段(2.1.152);公開回報涉及曾經通過 Claude 無法驗證之處的歷史記錄——例如相同 base URL 後方的非 Claude 模型、寫入自有簽章的代理伺服器,或遺失簽章的用戶端。切換後移除一次思考區塊。
Claude Code 會自動修復嗎?
近期版本會嘗試修復。自 2.1.152 起,它會在模型或登入切換後移除過時簽章,並在簽章遭拒時不帶先前思考區塊重試。這項重試會比對上游錯誤文字,而 Anthropic 的閘道指南指出,將錯誤包裝在自有信封中的閘道可能會使其失效。請先執行 claude update;如果某個工作階段在每一回合仍然失敗,請開始新的工作階段。