目次
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.
厄介なのは 「一度出ると、その後何を入力しても同じエラーが繰り返される」こと。タイプしても、Enterを押しても、同じ400エラー。セッションが 「詰み」状態になる。これは Anthropic公式リポジトリでも複数のIssue(#10199, #12225, #13012, #22278, #63147 など)が立っている 既知のバグだ。
結論から書く:原因は「拡張思考(extended thinking)の thinking ブロックが、会話履歴の再送時に壊れること」。thinking ブロックには 暗号署名(signature)が付いており、APIは 署名と中身をバイト単位で照合する。Claude Code が履歴を再構築する際に thinking の中身だけ空にして署名を残す等のバグで署名が一致しなくなり、APIが拒否する。最速の脱出は「Escを2回押して /rewind でチェックポイントに戻る」、ダメなら新セッション開始。本記事では仕組み・5つの主因・ユーザー向け3解決法・開発者向け対策・再発防止までを整理する。
thinking ブロック改変エラーの全体像
— 「署名」が一致しないと API は会話を丸ごと拒否する
Anthropic公式リポジトリで複数Issue報告済みの 既知バグ。
本質は 「thinking ブロックは原文のまま保持しなければならない」という API の厳格な制約。
1. このエラーは何を言っているのか
エラー文を日本語に直すとこうなる:「最新のアシスタントメッセージ内の thinking または redacted_thinking ブロックは変更できません。これらのブロックは元の応答のまま保持される必要があります」。
つまり API はこう言っている:「あなた(クライアント)が送ってきた会話履歴の中の『思考ブロック』が、私が前回返したものと違う。改変されている。だから受け付けない」。Claude API はマルチターン会話で 「前回の応答をそのまま履歴に含めて送り返す」のが前提だが、thinking ブロックだけは特に「一字一句変えるな」という強い制約がかかっている。messages.3.content.40 は 「4番目のメッセージの41番目のコンテンツブロック」を指し、そこに問題があるという位置情報だ。
重要なのは 「これはあなたのコードやプロンプトのミスではない」ケースが大半だということ。Claude Code 自身が 会話履歴(セッションJSONL)を再構築する際のバグで thinking ブロックを壊してしまうのが主因。だから 「自分の使い方が悪いのか?」と悩む必要はない——既知のバグであり、回避策がある。
2. 背景:拡張思考(thinking)と「署名」の仕組み
なぜ thinking ブロックだけこんなに厳格なのか。それは 拡張思考(extended thinking)の仕組みに理由がある。
Claude が拡張思考を有効にして応答すると、回答の前に 「思考ブロック(thinking block)」を生成する。これは Claude が 「どう考えたか」の途中経過で、最終回答の質を上げるための内部推論だ。このブロックには 暗号署名(signature)が付与される——「この思考内容は確かに Claude が生成したもので、改変されていない」ことを保証する電子署名のようなものだ。
マルチターン会話やツール使用(tool use)のループでは、過去のやり取り全体を毎回 API に送り返す。このとき thinking ブロックも一緒に送る必要があるが、署名は「元の思考テキスト全体」に対して計算されているため、テキストが1文字でも変わると署名照合が失敗する。API はセキュリティ上、署名が一致しない thinking ブロックを拒否する。これが400エラーの正体だ。
なぜ署名が必要なのか
思考ブロックの改変を防ぐことで、プロンプトインジェクションや思考の偽装を防止している。「Claude が実際にこう考えた」という事実を守るためのセキュリティ機構であり、厳格さには理由がある。
3. なぜ起きるのか——5つの主因
署名不一致が起きる具体的なシナリオは5つに整理できる。Anthropic公式Issueとコミュニティ報告を統合した。
署名不一致の5つの主因
共通点:「thinking ブロックが原文と1バイトでも違う」と必ず400。
CAUSE 1〜4 は Claude Code/プロキシ側のバグ、CAUSE 5 は自作実装の問題。
4. 今すぐ直す3つの方法(Claude Codeユーザー向け)
セッションが詰んだとき、復旧の速い順に3つの方法を試す。
復旧の速い順 3手
/rewind 実行。壊れたターンの 直前のチェックポイントに戻る。文脈を保ったまま復旧できる最善手。/clear または新規セッション開始。最も確実だが文脈を失う。重要な作業内容は事前にメモ/コミットしておく。
まず FIX 1(Esc×2 / rewind)。ダメなら FIX 2。文脈をどうしても残したいなら FIX 3。
そして必ず Claude Code を最新版に更新(Anthropicが順次修正中)。
FIX 3 の補足:コミュニティが 「Claude Code thinking blocks fix」というツール(GitHub の miteshashar/claude-code-thinking-blocks-fix 等)を公開している。これは セッションJSONL から全 thinking content ブロックを除去し、会話履歴は保ったまま署名問題を根絶する。頻発する人・長時間セッションを多用する人は導入する価値がある。ただし 非公式ツールのため自己責任、JSONLのバックアップを取ってから使う。
そして 最重要の恒久対策は「Claude Code を最新版に保つ」こと。claude update または公式の更新手順で最新版へ。Anthropic はこの一連のバグ(#10199, #12225, #63147 等)に対し 「空本文+署名の thinking ブロックを送る前に検出して除去する防御ガード」を順次実装している。古いバージョンほど遭遇しやすい。
5. 開発者向け:自作アプリ(API/SDK)で防ぐ
Claude API / SDK を 自分で叩いてアプリを作っている場合(拡張思考+ツール使用の組み合わせ)、同じエラーに自作実装で遭遇する。防ぐ原則は3つ。
// ❌ NG: thinking ブロックを削除・改変して送り返す
const history = previousMessages.map(m => ({
...m,
content: m.content.filter(b => b.type !== 'thinking') // 署名と不整合
}));
// ✅ OK パターン1: thinking ブロックを「丸ごとそのまま」保持
// API が返した assistant message を一切加工せず履歴に積む
messages.push(assistantMessageFromApi); // signature 付きのまま
// ✅ OK パターン2: 過去ターンの thinking は「完全に落とす」
// 空文字+署名ではなく、ブロック自体を含めない
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'
),
};
});
// ※ ただし「最新の」assistant message では落とさない(tool use 継続時)
3原則を整理する:① 署名付き thinking 本文を完全保存して、そのまま往復させる(round-trip)。② 過去ターンの thinking を送らないなら、ブロックごと完全に除去する(空文字+署名の中途半端が最悪)。③ リクエスト構築時に「本文が空なのに署名がある」thinking ブロックを検出して除去する防御ガードを入れる。
ツール使用ループでの鉄則
拡張思考+ツール使用(tool_use → tool_result)のループでは、「最新の」assistant message の thinking ブロックは絶対に改変しない。tool_result を返す次のリクエストで、直前の thinking + tool_use を原文のまま含める必要がある。Claude Agent SDK や Vercel AI SDK を使う場合、ライブラリ側がこの処理を正しく実装しているか確認する。
6. 似たエラーとの見分け方
thinking 関連の400エラーは複数あり、混同しやすい。代表的な3つを見分ける。
| エラー文 | 意味 | 主な対処 |
|---|---|---|
| thinking blocks ... cannot be modified | 本記事の主題。署名と中身が不一致 | /rewind・新セッション・最新版更新 |
| Invalid signature in thinking block | 署名そのものが無効(プロキシ改変が多い) | プロキシ設定見直し・直接API接続 |
| The final block in an assistant message cannot be thinking | assistant メッセージが thinking で終わっている(末尾に text や tool_use が必要) | メッセージ構造の修正・SDK更新 |
共通する根本原因は 「拡張思考のブロックを正しく扱えていない」こと。Claude Code 利用なら 大半が /rewind + 最新版更新で解決。自作アプリなら メッセージ構造とライブラリ実装の見直しが必要だ。プロキシ(CLIProxyAPI、各種ゲートウェイ)経由の場合は プロキシが thinking を改変していないかを最初に疑う。
7. 再発防止チェックリスト
頻発を防ぐための実践チェックリスト。
Claude Code ユーザー:① claude update で常に最新版を保つ(最大の予防策)。② 超長時間セッションは適度に /clear でリセット(混線リスク低減)。③ 重要な作業は こまめに git commit(詰んでも復旧できる)。④ エラー頻発時は JSONL修復ツールの導入を検討。⑤ 再現したら Anthropic公式Issueに報告(修正が早まる)。
API/SDK 開発者:① assistant message は API応答を加工せずそのまま履歴へ。② 過去 thinking を落とすなら ブロックごと完全除去(空文字+署名禁止)。③ リクエスト構築に 防御ガード(空本文+署名検出→除去)。④ 公式SDK(最新版)を使い、自前のメッセージ整形を最小化。⑤ プロキシ経由なら thinking 透過性を検証。
まとめ
Claude Code の 「thinking blocks ... cannot be modified」400エラーは、拡張思考の thinking ブロックが会話履歴の再送時に壊れ、暗号署名と中身が一致しなくなることで発生する。Anthropic公式リポジトリで複数Issue報告済みの 既知バグであり、大半はあなたの使い方のせいではない。主因は5つ——セッション再開バグ(最多)・ストリーミング混線・修復ロジック暴走・第三者プロキシ・自作アプリの履歴改変。
Claude Code ユーザーの最速復旧は ① Esc×2 / `/rewind` でチェックポイントに戻る、ダメなら ② 新セッション(/clear)、文脈温存なら ③ JSONL修復ツール。そして 最重要の恒久対策は「Claude Code 最新版更新」——Anthropic が防御ガードを順次実装している。API/SDK開発者は 「thinking ブロックを原文のまま往復させる/落とすなら完全除去する/防御ガードを入れる」の3原則を守る。
関連記事: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. 拡張思考(thinking)をオフにすれば回避できますか?
A. 理論上は回避できますが、拡張思考は 複雑なタスクの精度を大きく上げる機能なので、オフにするのは推奨しません。まずは 最新版更新+/rewind運用で対処し、それでも頻発する特殊環境(プロキシ経由等)でのみ、最終手段として検討してください。
Q. JSONL修復ツールは安全ですか?
A. 非公式ツールのため自己責任です。使う前に必ず セッションJSONLのバックアップを取ってください。仕組みは「thinking content ブロックを全削除し会話履歴は保持」で、原理的には安全ですが、公式の修正(最新版更新)が根本解決であることは変わりません。
Q. 自作アプリで tool use と thinking を併用したらこのエラーが出ます。
A. 「最新の assistant message の thinking ブロックを改変している」のが原因です。tool_result を返す次のリクエストで、直前の thinking + tool_use ブロックを API応答のまま(署名付きで)含める必要があります。過去ターンの thinking を削るなら ブロックごと完全除去(空文字+署名は禁止)。公式SDK最新版を使えば多くは自動処理されます。