If you moved an agent harness to Claude Fable 5.1 and started seeing a 400 whose message says a thinking block “is bound to a different conversation,” your code edits conversation history between requests, and Fable 5.1 is the first Claude model that objects. This guide explains what the check is, who it applies to, exactly what triggers it, the escape hatch, and the append-only patterns that make the error go away while also keeping your prompt cache warm.
The check is documented under preserved thinking and in What’s new in Claude Fable 5.1. It is the third of Fable 5.1’s three breaking changes, and the only one that can degrade a harness silently. For the other two, see the migration guide.
The error
messages.5.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". That setting requires the `thinking-binding-controls-2026-08-01` value in the `anthropic-beta` header.
It is a 400 invalid_request_error, decided before any output. Retrying the same body fails the same way. The path (messages.5.content.0) points at the first thinking block that no longer matches, and the message can end with one more sentence naming the first message that changed, which is the diagnostic you want. The token-counting endpoint runs the same check.
A different failure looks similar but is not this one: the same leading clause without the “bound to a different conversation” sentence means the signature itself is tampered or undecryptable, and prefix_mismatch_behavior does not apply.
What the check does
Every Fable 5.1 thinking block carries a signature that records two things: which model produced it, and the exact conversation prefix that preceded it, meaning the top-level system prompt, the tools array, and every message before the block. Each block also chains to the previous thinking block. When you send the transcript back, the API verifies that prefix is byte-identical to what produced the block.
Anthropic gives two reasons. The stated one is anti-distillation: the launch post says new API accounts can no longer manually edit Claude’s prior context in a multi-turn conversation while preserving the transcript of prior thinking, which closes a documented distillation technique. The practical one is that the same edits that break the check also restart the prompt cache, so code that passes the check is also code that gets the $0.25-per-million cache reads on every turn.
Who it applies to
Enforced by default: accounts created on or after August 31, 2026. That covers Claude API organizations, Amazon Bedrock accounts, Google Cloud projects, and Microsoft Foundry resources.
Recorded but not enforced: accounts created earlier. The API notes the mismatch but acts on it only when the request sets thinking.block_binding.prefix_mismatch_behavior to any value, including "error". Anthropic says future models will enforce it for everyone.
Not affected: Claude Code, claude.ai, Claude Managed Agents, and the Claude Agent SDK, which keep the prefix intact for you. Claude Mythos 5.1 does not run the check at all, though history edits still restart its cache.
Affected: any code that builds the messages array itself. That is every custom agent loop, every chat backend, and every framework that wraps the Messages API.
The trap for tool authors: if you ship something people run with their own API keys, your key is probably on an older account and theirs may not be. Test with the field set, so you hit the check before your users do. To learn whether your own account is enforced, send a request that edits history without the beta header; a 400 naming the header means it is.
What invalidates every later thinking block
- Editing, reordering, or removing an earlier turn. That includes deleting old tool results, snipping turns from the middle of the transcript, and client-side compaction that keeps recent turns verbatim behind a summary.
- Injecting content you do not persist. A per-turn reminder appended after the tool results and removed on the next request. A status line. A remaining-token count that changes each turn.
- Rebuilding
systemortoolsbetween requests. Updating the current date in the system prompt. Adding or removing a tool mid-session. - An image or document URL that serves different bytes later. The bytes are bound, not the URL string, so a rotating signed URL for the same file is fine.
- Removing a thinking block from anywhere other than the start of the run. Leading blocks can go, oldest first. A block from the middle cannot.
What keeps them valid
- Append-only histories, including appended
role: "system"messages and cleared turn-scoped messages left in place. - Removing a leading run of thinking blocks, oldest first.
- Changing any parameter outside
system,tools, andmessages:max_tokens,output_configincludingeffort,tool_choice,metadata. - Adding, moving, or removing
cache_controlmarkers. - Server-side compaction and context editing, including thinking-block clearing. They do not count as edits because the check compares the conversation as you sent it, not the server’s edited copy. After a compaction, the checked prefix starts from the compaction block.
The escape hatch: drop_block
Send the thinking-binding-controls-2026-08-01 beta header and set the field explicitly:
response = client.beta.messages.create(
model="claude-fable-5-1",
max_tokens=16000,
thinking={"type": "adaptive", "block_binding": {"prefix_mismatch_behavior": "drop_block"}},
betas=["thinking-binding-controls-2026-08-01"],
messages=history,
)
for t in response.input_transformations or []:
print(t.type, t.path, t.reason)
With "drop_block", the API drops the first mismatched block and every thinking block after it, proceeds with the request, and reports each drop in a top-level input_transformations array:
"input_transformations": [
{"type": "thinking_dropped", "path": "messages.1.content.0", "reason": "prefix_binding_mismatch"}
]
Three things to know about the field. It applies to that request only, so keep sending it for the rest of the session. The defaults differ by surface: without the header, an enforced account errors; sending the header alone switches to the beta’s own default, which is drop_block; so set it explicitly and never rely on either default. And sending block_binding without the header is a 400 ending in block_binding: Extra inputs are not permitted.
The reason field distinguishes two cases. prefix_binding_mismatch means your history changed. model_binding_mismatch means the conversation switched models (a router, a retry, a refusal fallback) and the target could not read a Fable 5.1 block. The second is not a bug in your code. With the header, every response carries the array, empty when nothing was dropped.
Dropping blocks once, at a compaction boundary, costs little. A harness that invalidates its own history on every request loses the model’s reasoning every turn and restarts the prompt cache every turn, and Anthropic warns that raises cost per task. Treat drop_block as a diagnostic and a safety net, not a steady state.
The no-beta recovery
On a platform without the controls (Microsoft Foundry did not offer them at launch; Bedrock and Google Cloud were adding them per model), strip every thinking and redacted_thinking block from the history, keep each turn’s text and tool_use blocks, and retry once. The model answers that turn without the reasoning those blocks carried. This is a one-time recovery, not a pattern.
The three-step audit
Run this before you switch traffic, not after.
- Capture the exact request bodies your harness sends over a few normal turns, including a compaction or a tool change if your product has them. For each pair of consecutive requests, diff the
systemprompt, thetoolsarray, and the shared prefix ofmessages. They should be byte-identical up to the newly appended turns. - Run a normal multi-turn session against
claude-fable-5-1with the beta header andprefix_mismatch_behavior: "drop_block", logginginput_transformationson every response. An empty array every turn means the history is intact. Aprefix_binding_mismatchentry means something before the block atpathchanged. This works from any account, because setting the field opts the request into enforcement. In CI, set"error"instead so an edit fails the run. - Choose a production setting and set it explicitly under the header:
"error"if a mismatch can only mean a bug,"drop_block"to degrade instead of fail. Monitor the 400s or theinput_transformationsentries either way. Do not leave the field unset on an older account, because then the check only records server-side and you get nothing to monitor.
In Apidog, step 2 is a two-request test: send a turn, edit the system prompt, send the next turn with the header set, and assert on input_transformations. Keep it in the collection so every harness change re-runs it. Download Apidog to build it.
Making a harness append-only
Each row replaces a history edit with something that keeps the prefix intact and keeps the cache warm.
| You were doing | Do this instead |
|---|---|
| Editing the system prompt mid-session (new date, new mode) | Freeze system at session start. Append {"role": "system", "content": "The current date is 2026-09-14."} at the point the change becomes true (mid-conversation system messages). No beta header; it gets system-prompt authority and becomes part of the prefix later blocks are bound to. |
Editing the tools array mid-session |
Declare the full set at session start (defer_loading: true on the ones that start hidden). Send tool_addition and tool_removal blocks in a role: "system" message (beta mid-conversation-tool-changes-2026-07-01). |
| Injecting a per-turn reminder and deleting it next request | Send it as a turn-scoped system message: {"role": "system", "clear_at": "next_user_message", "content": "..."} (beta mid-conversation-system-clear-at-2026-08-21) after the tool-result message, and leave every earlier copy in place. Cleared copies render nothing and cost nothing. Without the beta, put the reminder in a text block after the tool_result blocks in the same user message, earlier copies kept. |
| Deleting old tool results client-side | Server-side context editing with tool-result clearing. |
| Compacting on the client | Prefer server-side compaction (beta compact-2026-01-12; its instructions parameter takes your own summarization prompt). If you stay client-side, use simple compaction: replace the whole history with one summary message plus the new user turn and replay nothing else. |
| Referencing an image or document by URL across turns | Upload once to the Files API and send the file_id, or send base64. |
Two client-side compaction shapes break under the check and need drop_block or stripped thinking blocks on the retained turns. Keep-tail compaction (summarize older turns, keep the most recent verbatim) fails on the retained turns, because their thinking was produced against the full history. Background compaction (build the summary off the critical path and swap it in later) fails on every turn produced between the start of the summary and the swap. Snipping individual turns out of the middle of the transcript invalidates every later block, and no client-side shape avoids it. Use a mid-conversation system message for the instruction change you were making, or server-side context editing for selective removal.
One more cost consideration: because cache reads are now $0.25 per million, compacting early to save money may no longer be the right tradeoff on Fable 5.1. Anthropic suggests experimenting with later compaction points.
Why this is also the cache story
Everything in the table above is also the list of things that restart a prompt cache. Fable 5.1 made cache hits four times cheaper than Fable 5 and made misses proportionally more painful, so an append-only harness gets paid twice: the thinking survives, and every turn reads the prefix at $0.25 instead of rewriting it at $12.50. The pricing breakdown has the numbers; the API walkthrough shows the turn-scoped and per-message-effort request shapes in context, the prompting guide covers which per-turn instructions are worth sending that way, and the Claude Code guide explains why Claude Code users never see this error.
FAQ
What does “The block is bound to a different conversation” mean? A Claude Fable 5.1 thinking block was replayed after something before it changed: the system prompt, the tools array, or an earlier message. The API rejects the request with a 400 on enforced accounts.
Which accounts enforce the Fable 5.1 history check? Accounts created on or after August 31, 2026, on every platform. Older accounts enforce it only when a request sets thinking.block_binding.prefix_mismatch_behavior. Anthropic plans to enforce it for everyone on future models.
How do I make the error go away quickly? Send the thinking-binding-controls-2026-08-01 beta header with prefix_mismatch_behavior: "drop_block". The API drops the affected blocks and continues. Then fix the history edit, because dropping blocks every turn costs reasoning and restarts your cache.
Does changing effort or max_tokens invalidate thinking blocks? No. Any parameter outside system, tools, and messages can change freely, and so can cache_control markers.
Does server-side compaction break the check? No. Compaction and context editing happen after the check, which compares the conversation as you sent it. Client-side compaction that keeps recent turns verbatim does break it.
Does Claude Mythos 5.1 have the same check? No. Mythos 5.1 does not run the conversation check, though it still binds thinking blocks to the producing model and history edits still restart its cache.



