Claude 报 Invalid signature in thinking block(400):原因与修复

Wokey Team · 2026-10-30

结论先说: Invalid `signature` in `thinking` block 是 Claude 返回的 400,意思是对话历史里有一个 thinking 块没通过校验。要么签名不是 Claude 签发的(空的、被截断、被改过,或者来自别的厂商),要么在最新的几个模型上,这个块生成之后,它前面的对话内容被改动了。换 Claude 账号或换 API key 不会触发这个错误。原样重试也没用:要把历史里的 thinking 块去掉,或者开一个新对话。

报错有两种写法

报错 哪里没通过
messages.N.content.N: Invalid `signature` in `thinking` block 签名本身校验失败:为空、被截断、被改过,或者根本不是 Claude 签发的
…Invalid `signature` in `thinking` block. The block is bound to a different conversation. Remove the block, or set `thinking.block_binding.prefix_mismatch_behavior` to "drop_block". 前缀检查:这个块生成之后,system 提示词、tools 或更早的消息被改了

前缀检查适用于 Claude Fable 5.1、Opus 5.5、Sonnet 5.5 和 Haiku 5.5。2026 年 8 月 31 日及之后创建的账号默认强制执行;任何设置了 thinking.block_binding 的请求也会执行。完整的 API 返回长这样:

{"type":"error","error":{"type":"invalid_request_error","message":"messages.1.content.0: Invalid `signature` in `thinking` block"},"request_id":"req_011C..."}

同一套历史校验还会报两个相近的错误:Invalid `data` in `redacted_thinking` block,以及 `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified(后者表示 thinking 的文字本身被改过)。

在 Claude Code 里

Claude Code 显示为 API Error: 400 … Invalid `signature` in `thinking` block。较新的版本能识别这个错误,会去掉历史里的 thinking 块再重试,所以会话通常能继续,你什么都看不到。如果每一轮都报这个错,先升级(claude update)。2.0 系列这类旧版本不会自动恢复。升级后还报,用 /rewind 回到出问题之前的那一轮,或者 /clear 重新开始。

原因一:历史来自别的厂商

只要在同一个对话里用过不止一家厂商,这就是最常见的原因。不少非 Anthropic 的模型提供兼容 Anthropic 的接口,也会返回自己的 thinking 块。这些块的 signature 字段里是那家厂商自己的字符串,或者干脆为空,Claude 两种都校验不了。

所以对话先在别的模型上进行、再转到 Claude 时,就会报这个错:

  • 会话中途用配置切换工具或改 ANTHROPIC_BASE_URL 换了厂商;
  • 在网关上用 /model 从非 Claude 模型(比如 DeepSeek)切到 Claude,还是同一个会话;
  • 续用了一个在别的厂商那里开始的会话。

在 Wokey 上也一样。Wokey 收到什么 thinking 块就原样转发什么,不改写也不剥离,所以对话前面由 DeepSeek 生成的块,到了 Claude 那里带的仍然是 DeepSeek 的签名。

在 Claude 模型之间切换,或者在 Claude 账号之间切换,情况不同。某个 Claude 模型读不了另一个 Claude 模型写的块,或者读不了另一个账号生成的 Sonnet 5.5、Haiku 5.5 的块时,API 会静默丢掉这个块,请求照常成功。

原因二:客户端存错了

API 要求每个助手回合原样发回。客户端常见的破坏方式:

  • 只保存了 thinking 文字,没保存 signature;
  • 拼接流式响应时漏了 signature_delta 事件;
  • 对签名字符串做了裁剪、截断或重新编码;
  • 把同一个 thinking 块复制进了好几条消息。

Opus 5.5、Sonnet 5.5、Haiku 5.5 和 Fable 5.1 默认返回的 thinking 块里,thinking 字段是空的,推理内容在 signature 里。这样的块是完整的,要原样发回。

原因三:对话被改过(前缀检查)

带 “bound to a different conversation” 的那种写法,说明这个块之前的历史对不上了。常见原因:改了、调换了或删了更早的回合;每一轮都重新拼 system 提示词或 tools 数组;删掉了之前插入的提醒;客户端自己做压缩时,保留了最近几轮和它们的 thinking。

自己写代码时怎么修

助手回合原样发回。 保留完整的 content 数组,包括 thinking 块和签名,不要从文字重新拼。

历史来自别的厂商时,发给 Claude 之前先去掉 thinking。 删掉所有 thinking 和 redacted_thinking 块,每个回合里的其他块保留:

def strip_thinking(messages):
    cleaned = []
    for message in messages:
        content = message["content"]
        if message["role"] == "assistant" and isinstance(content, list):
            content = [b for b in content if b.get("type") not in ("thinking", "redacted_thinking")]
        cleaned.append({**message, "content": content})
    return cleaned

前缀检查那种写法,要让历史只追加、不修改。新的指令作为新消息加进去,不要改 system 或 tools。想让这次请求不带过期的推理继续下去,可以发送 beta 头 thinking-binding-controls-2026-08-01,并把 thinking.block_binding.prefix_mismatch_behavior 设为 "drop_block";或者按上面的方法去掉 thinking 块,再重试一次。

常见问题

换 Claude 账号或 API key 会导致这个错误吗?

不会。签名不会因为换账号而失效。唯一和账号绑定的是 Sonnet 5.5 和 Haiku 5.5 的 thinking 块,换了账号时 API 会静默丢掉它们,请求照常成功,不会返回 400。

重试能解决吗?

原样重试不能,同一个请求体每次都会被拒。要么删掉历史里的 thinking 和 redacted_thinking 块再发,要么开新对话。前缀检查那种报错,还可以发送 beta 头 thinking-binding-controls-2026-08-01 并把 thinking.block_binding.prefix_mismatch_behavior 设为 "drop_block"。

为什么从 DeepSeek 等模型切到 Claude 会报这个错?

这些模型的 Anthropic 兼容接口也会返回 thinking 块,但签名是它们自己的字符串,或者为空,Claude 校验不了。同一会话里切到 Claude 时,这些块被一起发过去,于是返回 400。切换厂商时开新会话,或者先把历史里的 thinking 块删掉。

Claude Code 里一直报这个错怎么办?

较新的 Claude Code 会自动去掉 thinking 块并重试,所以先运行 claude update 升级。升级后仍然每轮都报,用 /rewind 回到出问题之前的那一轮,或者用 /clear 开始新对话。