目录
你是否曾在 Claude Code 中工作时,突然冒出这个错误,然后整个会话彻底失去响应?
API Error: 400 messages.3.content.40: `thinking` or
`redacted_thinking` blocks in the latest assistant message
cannot be modified. These blocks must remain as they were
in the original response.
最难受的地方在于:一旦出现,之后无论输入什么都会触发同样的错误。你打字、按下回车,还是同样的 400。会话进入"卡死"状态。这是一个 已知缺陷,在 Anthropic 官方仓库上有多个未关闭的 issue(#10199、#12225、#13012、#22278、#63147 等)。
先说结论:原因是"在重新发送对话历史时,extended thinking 块被破坏了。"thinking 块带有加密 signature,而 API 会逐字节地用内容校验签名。当 Claude Code 带着缺陷重建历史时——例如把 thinking 文本清空却保留了 signature——签名就不再匹配,API 随之拒绝。最快的脱身办法是"按两次 Esc 并 /rewind 回退到检查点,"或者开启新会话。本文讲解机制、5 个根本原因、3 种面向用户的修复、面向开发者的对策,以及防止再次发生的方法。
thinking 块错误的全貌
— 若 signature 不匹配,API 会拒绝整段对话
Anthropic 官方仓库上有多个 issue 的已知缺陷。
本质:API 的严格规则——"thinking 块必须与原始响应中完全一致。"
1. 这个错误到底在说什么
用大白话讲,这条消息的意思是:"最新一条助手消息中的 thinking 或 redacted_thinking 块不能被修改。这些块必须保持原始响应中的样子。"
也就是说,API 在告诉你:"你(客户端)发给我的对话历史里的 thinking 块,和我上次返回的不一样。它被改动过了。所以我不接受。"Claude API 假定在多轮对话中你会"把上一次的响应包含进历史并原样发回"——而 thinking 块尤其带有严格的"一个字符都不能改"约束。messages.3.content.40 是位置信息:"第 4 条消息的第 41 个内容块"就是出问题的地方。
关键点:大多数情况下这并不是你的代码或提示词的错误。主因是 Claude Code 重建对话历史(会话 JSONL)的方式存在缺陷,从而破坏了 thinking 块。所以不必纠结"是不是我用错了?"——这是有应对办法的已知缺陷。
2. 背景:extended thinking 与 signature 机制
为什么唯独 thinking 块这么严格?原因就在于 extended thinking 的工作方式。
当 Claude 在启用 extended thinking 的情况下回答时,它会在答案之前生成一个 "thinking 块"。这是 Claude 的中间推理——提升最终答案质量的内部"思考过程"。这个块会被赋予一个加密 signature——类似一种数字签名,保证"这段 thinking 内容确实由 Claude 生成,且未被改动。"
在多轮对话和 tool use 循环中,整段之前的交互每次都会发回 API。thinking 块也必须一并发送,但 signature 是基于"整段原始 thinking 文本"计算的——因此文本哪怕只改一个字符,签名校验也会失败。出于安全考虑,API 会拒绝 signature 不匹配的 thinking 块。这就是这个 400 错误的本质。
signature 为何存在
禁止修改 thinking 块可以阻止 prompt injection 与思考伪造。它是一种安全机制,保护"Claude 确实是这样思考的"这一事实——严格是有原因的。
3. 为什么会发生——5 个根本原因
signature 不匹配的具体场景可归为五类——综合自 Anthropic 官方 issue 与社区报告。
signature 不匹配的五个根本原因
共同点:只要 thinking 块与原始内容哪怕相差一个字节,就一定会得到 400。
原因 1–4 是 Claude Code / 代理的缺陷;原因 5 是自建实现的问题。
4. 立刻可用的三种修复(面向 Claude Code 用户)
当会话卡死时,按恢复速度顺序尝试三种方法。
按恢复速度排列的三种修复
/rewind。回退到出错那一轮之前的检查点。最佳之选——在保留上下文的同时恢复。/clear 或开启全新会话。最可靠,但会丢失上下文。先把重要工作记录下来或提交。
先试 修复 1(Esc×2 / rewind)。不行就用修复 2。若必须保留上下文,用修复 3。
并且始终把 Claude Code 更新到最新版(Anthropic 正在逐步修复)。
关于修复 3:社区已发布一款 "Claude Code thinking blocks fix" 工具(例如 GitHub 上的 miteshashar/claude-code-thinking-blocks-fix)。它会从会话 JSONL 中移除所有 thinking 内容块,在保留对话历史的同时根除 signature 问题。如果你经常遇到这个问题或大量使用长会话,值得采用。但它是非官方工具,请自担风险——运行前请备份 JSONL。
最重要的永久性修复是"让 Claude Code 保持最新版。"运行 claude update 或按官方更新步骤操作。针对这一系列缺陷(#10199、#12225、#63147 等),Anthropic 正在逐步推出"检测空文本加 signature 的 thinking 块并在发送前剥离的防御性守卫"。旧版本更容易遇到。
5. 面向开发者:在自己的应用中预防(API/SDK)
如果你自己构建调用 Claude API/SDK 的应用(extended thinking + tool use),你会在自己的实现里遇到同样的错误。三条原则可以预防。
// BAD: deleting/altering thinking blocks before sending back
const history = previousMessages.map(m => ({
...m,
content: m.content.filter(b => b.type !== 'thinking') // mismatches signature
}));
// GOOD pattern 1: keep thinking blocks "exactly as-is"
// Push the assistant message from the API into history untouched
messages.push(assistantMessageFromApi); // keep the signature intact
// GOOD pattern 2: "fully drop" thinking from past turns
// Don't send empty text + signature; omit the block entirely
const clean = previousMessages.map(m => {
if (m.role !== 'assistant') return m;
return {
...m,
content: m.content.filter(b =>
b.type !== 'thinking' && b.type !== 'redacted_thinking'
),
};
});
// NOTE: do NOT drop them from the "latest" assistant message (during tool use)
三条原则:① 完整保留已签名的 thinking 文本并原样往返。② 若不发送过去轮次的 thinking,就移除整个块(空文本加 signature 是最糟情况)。③ 在构造请求时加一道防御性守卫,检测"文本为空但有 signature"的 thinking 块并剥离。
tool use 循环的铁律
在 extended thinking + tool use 循环中(tool_use → tool_result),绝不要改动"最新"那条助手消息的 thinking 块。返回 tool_result 的下一个请求必须原样包含前面的 thinking + tool_use。如果你使用 Claude Agent SDK 或 Vercel AI SDK,请确认该库正确处理了这一点。
6. 与相似错误的区分
有几种与 thinking 相关的 400 错误,容易混淆。区分主要的三种。
| 错误消息 | 含义 | 主要修复 |
|---|---|---|
| thinking blocks ... cannot be modified | 本文主题。signature 与内容不匹配 | /rewind、新会话、更新到最新版 |
| Invalid signature in thinking block | signature 本身无效(常因代理改动) | 检查代理配置,直连 API |
| The final block in an assistant message cannot be thinking | 助手消息以 thinking 结尾(结尾需要 text 或 tool_use) | 修正消息结构,更新 SDK |
共同的根本原因是"没有正确处理 extended thinking 块。"对 Claude Code 用户来说,大多数情况通过 /rewind + 更新到最新版即可解决。对自建应用来说,需要检查消息结构与库的实现。如果经过代理(CLIProxyAPI、各类网关),首先怀疑代理改动了 thinking。
7. 防止再次发生的检查清单
一份防止频繁复发的实用清单。
Claude Code 用户:① 用 claude update 保持最新版(最重要的预防)。② 定期用 /clear 重置很长的会话(降低交错风险)。③ 重要工作频繁提交到 git(即便卡死也可恢复)。④ 若频繁复发,考虑 JSONL 修复工具。⑤ 把复现情况报告到 Anthropic 官方 issue(加快修复)。
API/SDK 开发者:① 把助手消息不加改动地放入历史。② 若要丢弃过去的 thinking,移除整个块(不要空文本加 signature)。③ 在构造请求时加一道防御性守卫(检测空文本加 signature → 剥离)。④ 使用最新官方 SDK,尽量减少自定义的消息重塑。⑤ 若处于代理之后,验证 thinking 的透传。
总结
Claude Code 的 "thinking blocks ... cannot be modified" 400 错误发生在重新发送历史时 extended thinking 块被破坏、加密 signature 不再与内容匹配之时。这是 Anthropic 官方仓库上有多个 issue 的已知缺陷,大多数情况下不是你的错。五个原因:会话恢复缺陷(最常见)、流式交错、修复逻辑失控、第三方代理,以及在自己的应用中改动历史。
对 Claude Code 用户而言,最快的恢复是① 按 Esc×2 / /rewind 回退到检查点;若不行,② 新会话(/clear);要保留上下文,③ JSONL 修复工具。最重要的永久性修复是"把 Claude Code 更新到最新版"——Anthropic 正在逐步推出防御性守卫。API/SDK 开发者应遵循三条原则:原样往返 thinking 块 / 丢弃时整块移除 / 加防御性守卫。
相关阅读:什么是 Claude Agent SDK、Vercel AI SDK 完全指南、什么是 Cursor、Claude Code/Cursor 部署工作流。
FAQ
Q. 这个错误是我的提示词或代码出了问题吗?
A. 大多数情况下不是。如果它出现在使用 Claude Code 时,几乎肯定是 Claude Code 侧的已知缺陷(会话历史重建的缺陷)。Anthropic 官方仓库上有多个 issue 处于开放状态,修复正在进行。无需自责。只有自建应用(直接调用 API)才需要检查自己的实现。
Q. /rewind 解决不了,接下来怎么办?
A. 开启新会话(/clear)最可靠。你会丢失上下文,但一定能脱离卡死状态。先用 git commit 或记录保存好重要工作。若复发,把 Claude Code 更新到最新版;若仍然出现,考虑 JSONL 修复工具。
Q. 关掉 extended thinking 能避免它吗?
A. 技术上可以,但 extended thinking 能显著提升复杂任务的准确度,因此不建议关掉。先用更新到最新版 + /rewind 应对,只在特殊环境(例如代理之后)仍反复出现时,才把它作为最后手段考虑。
Q. JSONL 修复工具安全吗?
A. 它是非官方的,请自担风险。使用前务必备份会话 JSONL。其机制是"在保留对话历史的同时移除所有 thinking 内容块",原理上是安全的——但官方修复(更新到最新版)仍是真正的解决之道。
Q. 在我自己的应用里,把 tool use 与 thinking 结合会触发这个错误。
A. 原因是"你改动了最新那条助手消息的 thinking 块。"返回 tool_result 的下一个请求必须原样包含 API 返回的前面的 thinking + tool_use 块(连同 signature)。若丢弃过去轮次的 thinking,移除整个块(不要空文本加 signature)。最新官方 SDK 会自动处理其中大部分。