Claude「Invalid signature in thinking block」の直し方
Claude API からマルチターンの途中で Invalid signature in thinking block という400が返ってきたら、履歴のどこかを編集して送り返しています。thinking ブロックの signature は会話のプレフィックスに束縛されており、そこを変えると無効になる仕様です。2026年10月8日時点の情報です。
このエラーが出る理由
Fable 5.1、Opus 5.5、Sonnet 5.5、Haiku 5.5 の thinking ブロックは、それを生成した時点の会話のプレフィックス(トップレベルの system、tools の集合、そのブロックより前の全 messages)を signature に記録しています。次のリクエストで同じ履歴を送り返すとき、APIはこのプレフィックスが変わっていないかを検査します。変わっていれば、そのブロック以降の思考ブロックはまとめて無効です。
このチェックが働くのは、前の assistant 応答を messages に積んで送り返すコードだけです。1リクエストで完結する単発呼び出し(messages が毎回 user ターン1つだけ)は対象外なので、まず自分のコードが role: "assistant" の履歴を送り返しているかを確認してください。
厄介なのは、モデルがそのターンで実際に思考したかどうかで結果が変わる点です。思考ブロックが無ければ検査対象もないので、簡単な入力のテストでは何も起きず、本番の難しい入力で初めて400が出ることがあります。
今すぐ止める方法
方法1: 思考ブロックを剥がして再送する。 履歴から thinking と redacted_thinking を取り除き(text と tool_use はそのまま残す)、1回だけ再送します。その1ターンは前の推論を踏まえずに答えますが、エラーは止まります。毎リクエストでやる設計にはしないでください。推論もプロンプトキャッシュも毎回失います。
方法2: エラーではなく自動で落としてもらう。
response = client.beta.messages.create(
model="claude-fable-5-1", max_tokens=4096,
betas=["thinking-binding-controls-2026-08-01"],
thinking={"type": "adaptive", "block_binding": {"prefix_mismatch_behavior": "drop_block"}},
messages=messages,
)
print(response.input_transformations)
# [{"type": "thinking_dropped", "path": "messages.1.content.0", "reason": "prefix_binding_mismatch"}]
drop_block にすると、最初に不一致だったブロック以降の思考ブロックだけが落とされ、リクエスト自体は通ります。input_transformations を見れば、どこで履歴を壊したかが分かります。reason が model_binding_mismatch なら単にモデルを切り替えただけで、履歴編集のバグではありません。既定値はヘッダの有無で変わるため、"error" か "drop_block" を明示しておくのが安全です。
やってはいけない履歴編集
次の操作はどれも思考ブロックを無効にします。
- 古いターンの切り詰め(
messages[-20:]、messages.pop(0)) - リクエストごとの
systemの再構築 - リマインダーを直前のターンに差して次で消す運用
toolsの途中追加・削除- 古い
tool_resultの削除 - 画像URLの中身が後から変わる
逆に、追記のみの履歴、role: "system" メッセージの追記、思考ブロックを先頭から順に削る、tools の並べ替え、max_tokens や cache_control の変更は無効化を起こしません。
根本対策:編集を追記に置き換える
履歴を書き換えるのではなく、変化を末尾に追記する形に直すと、このエラーは根本的に起きなくなります。
| していたこと | 代わりに |
|---|---|
途中で system を書き換える | 開始時に固定し、変化したら {"role": "system", ...} を messages に追記する(GA、ヘッダ不要) |
途中で tools を書き換える | 開始時に全部宣言し、変更は tool_addition / tool_removal ブロックで追記する |
| リマインダーを差して消す | 履歴に残したまま clear_at 付きの turn-scoped システムメッセージにする |
| 古いターンの切り詰め | サーバー側の context editing や compaction を使い、クライアント側で削らない |
クライアント側で compaction をする場合は注意が必要です。直近のターンだけ原文で残す keep-tail 方式は、残したターンの思考ブロックが元の全履歴を前提に作られているため、やはり400になります。履歴の途中を抜く操作は、どの方式でも後続の思考ブロックを全部無効にします。
自分のループを検査する
- 隣り合うリクエストの
system・tools・messagesの共通プレフィックスがバイト単位で一致するか比較する thinking-binding-controls-2026-08-01とdrop_blockを付けて本番に近い難しさの入力でマルチターンを流し、毎応答のinput_transformationsが空配列かを確認する- 本番は設定を明示し、CIでは
"error"にして履歴編集があれば即座に失敗させる
2の確認を自動化するスクリプトを公開しています。
python claude5-migration-kit/history_check.py --model claude-opus-5-5 --turns 3
全手順とOpus 5.5での実測、アカウント境界の挙動、チェックスクリプトの詳細は元記事にまとめています。
動くコードと一緒に、体系的に学びたい方へ
よくある質問
- QInvalid signature in thinking block はバグですか?
- いいえ、仕様です。thinking ブロックの signature はそれを生んだ会話のプレフィックス(system・tools・それより前の messages)に束縛されており、履歴を編集して送り返すと無効と判定されます。
- Q今すぐ止血するにはどうすればいいですか?
- 送り返す履歴から thinking と redacted_thinking ブロックを取り除いて1回だけ再送する方法と、thinking-binding-controls-2026-08-01 ベータで prefix_mismatch_behavior を drop_block にしてAPI側に落としてもらう方法があります。
- Q自分のコードが影響を受けるかはどう確認しますか?
- messages に role: assistant の前回応答を積んで送り返しているかで判断できます。1リクエストで完結する単発呼び出しなら、このチェックには当たりません。
- Q対象はFable 5.1だけですか?
- いいえ。2026年9月のOpus 5.5・Sonnet 5.5、10月7日のHaiku 5.5にも同じ仕組みが入っています。2026年8月31日以降に作られた新しいアカウントで強制され、今後は対象が広がる予定です。
Claude API・AI エージェント開発の実践書
『Claude 5 世代 移行ガイド』『Claude Managed Agents 実践ガイド』を Zenn で販売中。全サンプルコードを GitHub で公開、冒頭の章は無料で読めます。
書籍を見る→関連記事
Claude「Invalid signature in thinking block」の直し方
Claude API がマルチターンの途中で『Invalid signature in thinking block』400を返すときの原因と対処をまとめます。履歴の先頭を削ると起きる仕様で、追記のみに直せば防げます。
Claude Haiku 5.5 移行でHTTP 400になる6つの原因と単価が5倍になる条件
Claude Haiku 5.5へmodelだけ書き換えるとbudget_tokensやtemperatureを渡している箇所でHTTP 400になります。実APIで確認した3つのエラーと、入力が10万トークンを超えると単価が5倍になる仕様を、直し方つきでまとめます(2026年10月12日時点)。
Claude Opus 5.5 の Fast mode を実測|速度2.26倍の料金と効く場面
Claude Opus 5.5のFast modeをstandardと交互に5回測りました。平均75.7 tok/sが171.0 tok/sになり2.26倍、料金は2倍です。効く場面・効かない場面と、切り替え時のキャッシュミスやレート制限の注意点をまとめます。
Claude Opus 5.5 / Sonnet 5.5 で 400 になる原因 5 つ
model だけを Opus 5.5 / Sonnet 5.5 に差し替えると HTTP 400 になる 5 つのケースを、thinking.type.disabled や tool_choice の実際のエラー文と直し方で解説します(2026年10月12日時点)。
