Invalid signature in thinking blockの原因と直し方 — 会話の前提が変わる400
thinking返送で出る「bound to a different conversation」の400。原因はsystem・tools・過去メッセージの変更で、署名破損とは文言で区別します。drop_blockの使いどころも扱います。
過去のthinking blockを送り返したリクエストが、次の400で拒否されることがあります。
messages.1.content.0: 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・メッセージのどれかが変わったことです。署名が壊れたわけではありません。同じボディを再送しても直らず、履歴を追記のみに戻すか、betaヘッダー付きでdrop_blockを指定して継続するかのどちらかになります。
このエラーが出る条件
Claude Fable 5.1、Claude Opus 5.5、Claude Sonnet 5.5、Claude Haiku 5.5では、再送したthinking blockが有効なのは、そのブロックより前のsystem・tools・メッセージが変わっていない間だけです。この「前にあるもの」を、ドキュメントは検査対象の接頭辞(prefix)と呼びます。
接頭辞に含まれるのは3つです。
- トップレベルの
systemプロンプト toolsの集合- ブロックより前の各
message
サーバー側のcompactionを使う場合、検査の起点は直近のcompactionブロックになります。
検査の対象外も決まっています。effort、max_tokens、output_config、tool_choice、metadataといったパラメータと、cache_controlマーカーの付け外しは、変えても無効になりません。
検査が効くアカウント
検査はすべてのアカウントで一律に効くわけではありません。2026年8月31日以降に作られたアカウントでは、既定で強制されます。それ以前のアカウントでは、thinking.block_binding.prefix_mismatch_behaviorをリクエストに設定したときだけ強制されます。
つまり、自分のキーで一度もエラーが出ていなくても、コードが接頭辞を書き換えていないとは言えません。ツールを他の人のキーで動かす場合は、新しいアカウントの利用者のほうが先に400を見ることになります。
Claude Code、claude.ai、Claude Managed Agents、Claude Agent SDKがリクエストを組み立てる場合は、利用者側の対応は要りません。自前でmessages配列を組むコードだけが対象です。
何が接頭辞の変更にあたるか
公式の一覧から、実装で踏みやすいものを抜き出します。
| 前回リクエストからの変更 | 以降のthinking block |
|---|---|
| 末尾へのメッセージ追加 | 以降のthinking block有効 |
effortやmax_tokensなどの変更 | 以降のthinking block有効 |
cache_controlの付け外し | 以降のthinking block有効 |
過去のuser/assistant/systemメッセージの編集・並べ替え・削除 | 以降のthinking block無効 |
system文字列やブロックの変更 | 以降のthinking block無効 |
toolsの追加・削除・名前変更・編集 | 以降のthinking block無効 |
過去のtool_resultを短くする、tool_useの入力を変える | 以降のthinking block以降すべて無効 |
| 初回ユーザーメッセージに入れた文脈を、値だけ変えて再生成する | 以降のthinking block全ブロック無効 |
| 同じバイト列を返さない画像・文書のURL | 以降のthinking block無効 |
| thinking blockを履歴の途中から1つだけ抜く | 以降のthinking block以降のブロックが無効 |
最後の行は見落としやすい点です。各thinking blockは、直前のthinking blockが何だったかを記録しています。古い側から削る、新しい側から削る、すべて削る、のいずれかは通ります。途中から1つ抜くと、系列に穴が空いて以降のブロックが無効になります。さらに、いったん外したブロックを後から戻すと、外れていた間に生成されたブロックが無効になります。
実運用で起きやすいのは、次のような場面です。
- ターンごとに時刻やリマインダーをsystemに差し込み、次のリクエストで消す
- 動的にツール定義を入れ替える
- クライアント側のcompactionで、直近のターンとそのthinkingだけを残して古いメッセージを要約に置き換える
- ログ圧縮のために、古い
tool_resultを短縮する
どれも、キャッシュヒット率も同時に落ちる操作です。公式も、thinkingを無効にする編集の大半はプロンプトキャッシュも再開始させると説明しています。
署名の破損とは文言で見分ける
同じInvalid signature in thinking blockで始まるエラーには、原因が2種類あります。切り分けの手がかりは、文のつづきです。
| メッセージの特徴 | 意味 | prefix_mismatch_behaviorの効果 |
|---|---|---|
The block is bound to a different conversation.が続く | 意味前の内容が変わった。署名は読めている | prefix_mismatch_behaviorの効果効く |
Invalid signature in thinking blockで文が止まる | 意味署名が検証できない。切り詰め・改変・空文字での返送 | prefix_mismatch_behaviorの効果効かない |
thinking/redacted_thinking blocks ... cannot be modified | 意味思考テキスト自体の編集や、redacted_thinkingの脱落 | prefix_mismatch_behaviorの効果別の対処。thinking blockの改変エラーの記事を参照 |
署名破損の側は、常に400になります。公式が挙げる原因は、署名が切り詰められた、改変された、空のまま返送された、の3つです。この場合はdrop_blockを指定しても通りません。
「bound to a different conversation」の側は、メッセージの末尾に、何が変わったかを示す一文が付くのが普通です。公式によれば、systemプロンプト、toolsのリスト、最初に違いが出たメッセージやブロック、足りない・新しいコンテンツ、先行するthinking blockの欠落や順序違いなどが名指しされます。ただしこの一文は人とログのためのもので、文言は変わりうるため、コードで文字列照合しないよう注意があります。
betaヘッダーを付けずに送った場合は、メッセージに「thinking-binding-controls-2026-08-01の値をanthropic-betaヘッダーに入れる必要がある」という一文も加わります。
直し方: 履歴を追記のみにする
根本の対処は、systemとtoolsをセッション中は固定し、messagesを追記のみで扱うことです。公式は、変更したいものごとの置き換え方を示しています。
接頭辞を触らずに変更を入れる
- 1
アシスタントのターンは返ってきたまま積む
thinking・redacted_thinkingを含むcontentをそのまま次のmessagesに入れます。フィルタや再構築は挟みません。 - 2
途中の指示はmid-conversation system messageで足す
systemを書き換える代わりに、会話の途中にsystemメッセージを追加します。配置の制約はmid-conversation system messageの記事にあります。 - 3
変わる文脈は最新のターンに置く
初回ユーザーメッセージを再生成せず、毎回変わる情報は最新のユーザーターンに入れます。
- 4
トリミングはサーバー側に任せる
サーバー側のcontext editingやcompactionでは、このエラーは起きません。検査が比べるのは利用者が送った内容で、サーバーが後から削った部分は対象外だからです。クライアント側で要約に差し替える場合の条件はcompactionで残したthinking blockの記事で扱っています。
Preserved thinkingそのものの背景はPreserved thinkingの解説にまとめています。
つなぎとしてdrop_blockを使う
すぐに直せない場合は、betaヘッダーthinking-binding-controls-2026-08-01を付け、thinking.block_binding.prefix_mismatch_behaviorに"drop_block"を指定します。
curl https://api.anthropic.com/v1/messages \
-H "anthropic-beta: thinking-binding-controls-2026-08-01" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "content-type: application/json" \
-d @request.jsonrequest.jsonのthinkingは、たとえば次の形にします。
{
"thinking": {
"type": "adaptive",
"block_binding": { "prefix_mismatch_behavior": "drop_block" }
}
}設定値は"error"(既定)と"drop_block"の2つです。drop_blockにすると、検査に失敗したブロックと、それより後ろのthinking blockをAPIが落とし、リクエストは成功します。落とされたブロックは課金されません。
ただし代償があります。
- モデルはその回、落とされた推論を使わずに答える
- 推論を作り直すぶん、出力トークンが増え、応答が遅くなることがある
- プロンプトキャッシュは編集した位置から再開始する
- 前の推論に依存する作業では、出力の質が変わる可能性がある
毎ターン落とすと、たまに落とす場合より増え幅が大きくなります。公式は、使う前に自分のワークロードで出力トークンの増加を測ることを勧めています。恒久設定ではなく、原因の編集を直すまでのつなぎと考えるのが安全です。
落ちたブロックを検知する
betaヘッダーを付けると、レスポンスのトップレベルにinput_transformations配列が付きます(ストリーミングではmessage_startイベント)。落ちたブロックごとに、次のような項目が入ります。
{
"input_transformations": [
{
"type": "thinking_dropped",
"path": "messages.1.content.0",
"reason": "prefix_binding_mismatch"
}
]
}reasonで原因が分かれます。
prefix_binding_mismatch: 前の内容が変わった。この記事の対象model_binding_mismatch: 会話の途中で別モデルに切り替え、前のモデルのブロックを読めない。接頭辞の編集ではなく、prefix_mismatch_behaviorの影響も受けないorganization_binding_mismatch: 別のアカウントが生成したブロック
セッションごとにprefix_binding_mismatchの件数を数えて通知を出せば、drop_blockで静かに通り続けている編集を見逃しません。CIでは"error"を指定して、退行をテストの失敗として拾う方法もあります。Message Batches APIでは、項目がこのフィールドを未設定にしても失敗しません。既定で検査が強制されるアカウントでは、検査に失敗したブロックが落とされます。項目を失敗させたいときは"error"を明示します。
モデルごとの制約
Claude Sonnet 5.5とClaude Haiku 5.5では、block_bindingはthinking: {"type": "adaptive"}でのみ使えます。Sonnet 5.5のbetween_toolsや、Haiku 5.5のthinking: {"type": "disabled"}と組み合わせると400になります。その場合は履歴を追記のみに保つか、編集したターン以降のthinking blockを取り除きます。
betaヘッダーなしでblock_bindingを送ると、メッセージがblock_binding: Extra inputs are not permittedで終わる別の400になります。
betaヘッダーが使えないときの手順
ヘッダーを付けられない環境では、履歴からthinkingとredacted_thinkingをすべて外して1回だけ再試行する方法があります。最低でも、エラーが名指ししたブロックと、そのターン以降のすべてのブロックを取り除きます。各ターンのtextやtool_useは残します。redacted_thinkingの形式はredacted_thinkingブロックの記事にあります。外したブロックは戻さずに、以降もそのまま続けます。
原因の編集は直しておく必要があります。直さないと、新しく生成されたブロックが次の編集で同じ理由で無効になります。
原因を特定する流れ
- 400の文末を読む。
bound to a different conversationなら接頭辞の変更、文が止まっているなら署名破損 - 接頭辞の変更なら、失敗したリクエストと、その前の成功リクエストのボディを保存して差分を取る
- 比べるのは
system、tools、共通するmessages。追記分を除いて同一のはず "error"のまま再送すれば、文末の一文が変更点を示すことがある- 見つけた編集を、上の置き換えパターンのどれかに変える
Claude Code上で出るthinking block mismatchの復旧は、/rewindで戻す手順の記事にまとめています。
まとめ
Invalid signatureに続く文が「bound to a different conversation」なら、署名は無傷で、接頭辞が変わっています。まず変更点を差分で特定し、system・tools・過去メッセージを追記のみにするのが本筋です。drop_blockは出力トークンの増加と引き換えの時間稼ぎとして、input_transformationsの件数を見ながら使います。