目次
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.
送り返した thinking ブロックの署名の検証に失敗すると、次のエラーとして表示されることもあります。どちらも thinking ブロックが元の応答のままではないことが原因です:
API Error: 400 messages.1.content.0:
invalid `signature` in `thinking` block
厄介なのは 「一度出ると、その後何を入力しても同じエラーが繰り返される」こと。タイプしても、Enterを押しても、同じ400エラー。セッションが 「詰み」状態になる。これは Anthropic公式リポジトリでも複数のIssue(#10199, #12225, #13012, #22278, #63147 など)が立っている 既知のバグだ。
結論から書く:原因は「拡張思考(extended thinking)の thinking ブロックが、会話履歴の再送時に壊れること」。thinking ブロックには 暗号署名(signature)が付いており、APIは 送り返された thinking ブロックが元の応答のままかを確かめる。Claude Code が履歴を再構築する際のバグで ブロックが元の応答と食い違うと、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 ブロックも一緒に送る必要がある。公式ドキュメントによれば、signature には思考の全体が暗号化されて入っており、API は送り返された署名で「Claude が生成した thinking ブロックか」を確かめ、サーバー側で署名を復号して元の思考を組み立て直す。画面に見える thinking 欄は思考の要約で、新しいモデルの既定(display: "omitted")では空になる。署名の値は表示の設定に関係なく同じで、omitted のブロックの thinking 欄に文字を入れても無視される。だから公式は thinking ブロックを受け取ったまま、改変せずに返すよう求めており、署名が欠けたり壊れたりしてブロックが元の応答と食い違うと、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 または公式の更新手順で最新版へ。Claude Code の changelog には、この系統の修正が繰り返し載っている——並行エージェントでの混線(2.1.47)、モデルやログインの切り替え後に残った古い署名を事前に取り除く処理(2.1.152)、Opus 4.8 で thinking ブロックが書き換わる問題(2.1.156)、redacted_thinking のエラーが出たら thinking ブロックを捨てて1回だけ再試行する処理(2.1.282)など。ただし #63147 は 2.1.157 でも再現したとの報告があり、2026年10月4日時点で未解決(open)のまま。古いバージョンほど、修正の入っていない経路が多い。
5. 開発者向け:自作アプリ(API/SDK)で防ぐ
Claude API / SDK を 自分で叩いてアプリを作っている場合(拡張思考+ツール使用の組み合わせ)、同じエラーに自作実装で遭遇する。公式ドキュメントが示す防ぎ方は1つに集約できる——API が返した assistant ターンを thinking ブロックごと受け取ったまま送り返し、新しいメッセージは末尾に足すだけにすることだ。
// ❌ NG 1: ブロックの種類を拾い直して assistant メッセージを作り直す
const rebuilt = {
role: 'assistant',
content: [
...response.content.filter(b => b.type === 'thinking'), // redacted_thinking が落ちる
...response.content.filter(b => b.type === 'tool_use'),
],
};
// ❌ NG 2: 本文が空で署名だけの thinking ブロックを「壊れている」と見なして消す
// 新しいモデルでは、これが正規の形(display の既定が "omitted")
// ✅ OK: API が返した assistant message を加工せずに積み、新しいメッセージは末尾に足す
messages.push({ role: 'assistant', content: response.content }); // thinking・redacted_thinking・署名ごと
messages.push({ role: 'user', content: [toolResult] });
① 本文が空で署名だけの thinking ブロックは正常。新しいモデルでは display の既定が "omitted" で、思考の全体は暗号化されて signature に入り、thinking 欄は空で返る。そのまま送り返せばよく、補ったり消したりしない(omitted のブロックの thinking 欄に文字を入れても無視される)。
② 過去ターンの thinking を自分で間引かない。全部送り返せば、API がモデルごとに必要な分だけ残して残りを自動で取り除き、入力の課金も実際に Claude に見せた分だけになる。ツール使用の途中でなければ過去ターンの thinking を省くこと自体は許されているが、新しいモデルでは thinking ブロックは「それより前の system・tools・メッセージが変わらない間だけ有効」で、途中のターンを書き換えたり一部のブロックだけ削ったりすると、後ろの thinking がすべて無効になって400(Invalid signature in thinking block)が返る(2026年8月31日以降に作られたアカウントなどで適用)。履歴を軽くしたいなら、サーバー側の context editing(thinking ブロックの消去)や compaction に任せる。
③ redacted_thinking も同じ扱い。type === 'thinking' だけを残す・除くフィルタは、redacted_thinking を黙って取りこぼす。公式のトラブルシューティングは、このエラーの最も多い原因として「ブロックを種類で絞り込んで redacted_thinking を落とす」ことと「assistant メッセージをそのまま返さずに作り直す」ことを挙げている(Thinking・Thinking troubleshooting、2026年10月4日時点)。
ツール使用ループでの鉄則
拡張思考+ツール使用(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 | 署名の検証に失敗。thinking ブロックが元の応答から改変・破損している(履歴の再構築のほか、途中のプロキシが内容を書き換えた場合も) | /rewind・新セッション・最新版更新。プロキシ経由なら設定も見直す |
| 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・redacted_thinking・署名ごと)。② 履歴は 末尾に足すだけにし、途中のターンを書き換えない・一部のブロックだけ削らない(間引きはサーバー側の context editing や compaction に任せる)。③ 本文が空で署名だけの thinking ブロックを消さない(新しいモデルの既定の形)。④ 公式SDK(最新版)を使い、自前のメッセージ整形を最小化。⑤ プロキシ経由なら thinking 透過性を検証。
まとめ
Claude Code の 「thinking blocks ... cannot be modified」400エラーは、拡張思考の thinking ブロックが会話履歴の再送時に壊れ、元の応答と食い違うことで発生する。Anthropic公式リポジトリで複数Issue報告済みの 既知バグであり、大半はあなたの使い方のせいではない。主因は5つ——セッション再開・履歴再構築のバグ・ストリーミング混線・修復ロジック暴走・第三者プロキシ・自作アプリの履歴改変。
Claude Code ユーザーの最速復旧は ① Esc×2 / /rewind でチェックポイントに戻る、ダメなら ② 新セッション(/clear)、文脈温存なら ③ JSONL修復ツール。そして 最重要の恒久対策は「Claude Code 最新版更新」——changelog には関連する修正が繰り返し載っている。API/SDK開発者は 「assistant ターンを 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. 拡張思考(thinking)をオフにすれば回避できますか?
A. 理論上は回避できますが、拡張思考は 複雑なタスクの精度を大きく上げる機能なので、オフにするのは推奨しません。まずは 最新版更新+/rewind運用で対処し、それでも頻発する特殊環境(プロキシ経由等)でのみ、最終手段として検討してください。
Q. JSONL修復ツールは安全ですか?
A. 非公式ツールのため自己責任です。使う前に必ず セッションJSONLのバックアップを取ってください。仕組みは「thinking content ブロックを全削除し会話履歴は保持」で、原理的には安全ですが、公式の修正(最新版更新)が根本解決であることは変わりません。
Q. 自作アプリで tool use と thinking を併用したらこのエラーが出ます。
A. 「最新の assistant message の thinking ブロックを改変している」のが原因です。tool_result を返す次のリクエストで、直前の thinking + tool_use ブロックを API応答のまま(署名付きで)含める必要があります。過去ターンの thinking を自分で削る必要はなく、新しいモデルでは一部のターンだけ削ると後ろの thinking が無効になります。本文が空で署名だけのブロックは新しいモデルの正規の形なので、そのまま返してください。公式SDK最新版を使えば多くは自動処理されます。
関連するClaude Codeエラー:Claude Codeエラー大全、「court」/invokeタグ漏れ、「Prompt is too long」。
関連記事: Claudeの適応的思考とは.