Claude Thinking Block Required in Continuation — Fix (2026) | AI Error Hub
Anthropic Claude Extended Thinking Severity: High HTTP 400

Claude Extended Thinking — Block Required in Continuation

When continuing a conversation that used extended thinking with tool_use, you MUST include the original thinking blocks in the assistant message history. Stripping them causes 400 errors or breaks the signature verification chain.

Error code: invalid_request_error HTTP: 400 Category: Extended Thinking Last tested: Nov 15, 2026
Quick Fix (TL;DR)

When appending an assistant response to messages history for the next turn, include ALL content blocks — thinking, redacted_thinking, text, and tool_use. Never filter to just the text. Signatures on thinking blocks are cryptographically verified; removing them breaks continuation.

The Error Messages You're Seeing

Response body variants
HTTP/1.1 400 Bad Request

{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "messages.1.content: assistant message with tool_use 
    is missing required thinking block from previous turn"
  }
}

Variants:
"thinking block signature invalid or missing"
"redacted_thinking block cannot be removed from history"
"When extended thinking is enabled, all thinking blocks 
must be preserved in assistant messages"
"Signature mismatch on thinking block"

Understanding Thinking Block Requirements

Why thinking blocks must persist

Claude's extended thinking uses cryptographic signatures to verify continuity. When Claude thinks, then calls a tool, then receives a tool result, then continues thinking — the signature chain proves the thinking wasn't tampered with. Removing thinking blocks between calls breaks the chain.

Correct message structure with thinking
messages: [ { role: "user", content: "Solve this complex problem..." }, { role: "assistant", content: [ { type: "thinking", thinking: "Let me work through this step by step...", signature: "abc123..." }, ← MUST preserve { type: "tool_use", id: "toolu_01", name: "calc", input: {...} } ]}, { role: "user", content: [ { type: "tool_result", tool_use_id: "toolu_01", content: "42" } ]}, { role: "assistant", content: [ { type: "thinking", thinking: "The result is 42. Now let me...", signature: "def456..." }, ← MUST preserve { type: "text", text: "The answer is 42." } ]} ]

What Actually Causes This Error

45%
Extracting only text from assistant responseCommon pattern: msg.content[0].text — drops thinking blocks.
25%
Filtering "internal" blocks before persistenceStoring conversation for UI display, then reusing filtered version for API.
15%
Custom serialization drops unknown fieldsOld code doesn't know about thinking/signature; silently drops them.
10%
Redacted thinking block removedTeam saw "redacted" and thought it was a placeholder to remove.
5%
Signature modified accidentallyCross-encoding (UTF-8/16), string interpolation corrupted signature.

Fixes That Work (Tested Nov 2026)

1Preserve ALL Content Blocks in History

Python · correct continuation pattern
def run_with_thinking(user_message): messages = [{"role": "user", "content": user_message}] while True: response = client.messages.create( model="claude-sonnet-4-5", max_tokens=4096, thinking={"type": "enabled", "budget_tokens": 10000}, tools=my_tools, messages=messages ) # CRITICAL: append entire content list, not just text messages.append({ "role": "assistant", "content": response.content # includes thinking blocks! }) if response.stop_reason == "end_turn": return response if response.stop_reason == "tool_use": tool_results = [] for block in response.content: if block.type == "tool_use": result = execute_tool(block.name, block.input) tool_results.append({ "type": "tool_result", "tool_use_id": block.id, "content": result }) messages.append({"role": "user", "content": tool_results}) # Loop continues; thinking blocks preserved

2Serialize With Full Fidelity

Python · Pydantic model dump for persistence
import json def serialize_message(msg): """Preserve all fields including thinking + signature.""" if hasattr(msg, "model_dump"): # Anthropic SDK returns Pydantic models return msg.model_dump(mode="json", exclude_none=True) return msg def save_conversation(messages, path): """Save conversation preserving thinking blocks.""" with open(path, "w") as f: for msg in messages: if isinstance(msg.get("content"), list): content = [serialize_message(c) for c in msg["content"]] out = {"role": msg["role"], "content": content} else: out = msg f.write(json.dumps(out) + "\n") def load_conversation(path): """Reload preserving all fields.""" with open(path) as f: return [json.loads(line) for line in f] # Signatures survive full round-trip

3Display vs API Storage Separation

Two representations of the same conversation

Store TWO versions: (1) full-fidelity for API calls (with thinking + signatures), (2) display-safe for user UI (thinking hidden or shown as collapsible). Never derive the API version from the display version — always keep the original.

Python · dual-representation pattern
class Conversation: def __init__(self): self._api_messages = [] # full fidelity def add_user(self, text): self._api_messages.append({"role": "user", "content": text}) def add_assistant_from_response(self, response): # Store full content including thinking self._api_messages.append({ "role": "assistant", "content": [serialize_message(c) for c in response.content] }) def for_api(self): """Send to Claude — includes thinking blocks.""" return self._api_messages def for_display(self, show_thinking=False): """Show user — filter thinking unless requested.""" display = [] for msg in self._api_messages: if isinstance(msg["content"], str): display.append(msg) continue visible = [c for c in msg["content"] if show_thinking or c["type"] not in ("thinking", "redacted_thinking")] display.append({"role": msg["role"], "content": visible}) return display

Preventing This Error Going Forward

  • Never mutate assistant.content when appending to history. Whole list, always.
  • Use Pydantic model_dump() for serialization. Preserves all fields.
  • Keep API history and display history separate. Don't derive one from the other.
  • Round-trip test after any serialization change. Load + resend + verify no error.
  • Log content block types on append. Alert if thinking blocks vanish.
SK
Tested by Sana K.
Researcher · AI Error Hub
Last verified: Nov 15, 2026 · SDK: anthropic 0.42

Frequently Asked Questions

Yes — that's the recommended pattern. Store the full content (with thinking) for API continuation; filter out thinking blocks when rendering to the user. Two views of the same source of truth.

Encrypted thinking content that Anthropic returns instead of plain text in specific cases (safety, IP protection). You get an opaque blob with a signature. You must include it in continuation just like regular thinking blocks. You can't decode it, but Claude uses it to maintain continuity.

Simple text-only responses that don't reference tools: technically you can strip thinking blocks and get away with it in one-shot completions. But if there's ANY chance of continuation or tool use, preserve them. Safe default: always preserve.

No, signatures are per-request. Don't try to cache thinking blocks across sessions. Treat them as one-shot payloads tied to their specific conversation continuation.

Yes. Every thinking token stays in the conversation history and counts toward the 200K context. Long agent runs with extensive thinking can blow through context quickly — plan budget accordingly.