openclaw - 💡(How to fix) Fix Bug: anthropic-transport-stream overwrites signature_delta instead of appending, causing permanent session corruption

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

The anthropic-transport-stream.ts (used by the embedded agent runner) overwrites thinkingSignature on each signature_delta event instead of appending to it. Since Anthropic sends the thinking block signature across multiple signature_delta streaming chunks, only the last chunk survives. The truncated signature is persisted to the session JSONL, and all subsequent replay attempts fail with:

400: messages.N.content.M: thinking or redacted_thinking blocks in the latest assistant message cannot be modified

This permanently bricks the session with no user recovery path other than /reset.

Error Message

  1. Error repeats on every subsequent turn - session permanently bricked
  2. THINKING_BLOCK_ERROR_PATTERN matches the error message
  • After a few turns, every subsequent request fails with the 400 thinking block error
  • #87475 - "Filter noisy invalid_request_error subtypes" - Reports the same Invalid signature in thinking block error reaching users. The wrapAnthropicStreamWithRecovery (#86886) single-retry cannot help because the signature is fundamentally truncated at storage time.
  • #87329 - Subagent echo messages with wrong provider metadata amplify the same thinking-block 400 error after gateway restart.

Root Cause

File: src/agents/anthropic-transport-stream.ts:1289

// BUG: overwrites instead of appending
block.thinkingSignature = delta.signature;

Correct implementation (same repo): src/llm/providers/anthropic.ts:629-634

// Correct: initializes then appends all chunks
block.thinkingSignature = block.thinkingSignature || "";
block.thinkingSignature += event.delta.signature;

Fix Action

Fix

// src/agents/anthropic-transport-stream.ts:1289
// Before:
block.thinkingSignature = delta.signature;

// After:
block.thinkingSignature = (block.thinkingSignature || "") + delta.signature;

Code Example

400: messages.N.content.M: thinking or redacted_thinking blocks in the latest assistant message cannot be modified

---

// BUG: overwrites instead of appending
block.thinkingSignature = delta.signature;

---

// Correct: initializes then appends all chunks
block.thinkingSignature = block.thinkingSignature || "";
block.thinkingSignature += event.delta.signature;

---

// src/agents/anthropic-transport-stream.ts:1289
// Before:
block.thinkingSignature = delta.signature;

// After:
block.thinkingSignature = (block.thinkingSignature || "") + delta.signature;
RAW_BUFFERClick to expand / collapse

Summary

The anthropic-transport-stream.ts (used by the embedded agent runner) overwrites thinkingSignature on each signature_delta event instead of appending to it. Since Anthropic sends the thinking block signature across multiple signature_delta streaming chunks, only the last chunk survives. The truncated signature is persisted to the session JSONL, and all subsequent replay attempts fail with:

400: messages.N.content.M: thinking or redacted_thinking blocks in the latest assistant message cannot be modified

This permanently bricks the session with no user recovery path other than /reset.

Root Cause

File: src/agents/anthropic-transport-stream.ts:1289

// BUG: overwrites instead of appending
block.thinkingSignature = delta.signature;

Correct implementation (same repo): src/llm/providers/anthropic.ts:629-634

// Correct: initializes then appends all chunks
block.thinkingSignature = block.thinkingSignature || "";
block.thinkingSignature += event.delta.signature;

Failure Mechanism

  1. Anthropic API sends the thinking block signature in N signature_delta chunks (base64 is long)
  2. Transport stream overwrites on each chunk - only last chunk survives
  3. Truncated signature stored in session JSONL
  4. Next request replays the truncated signature - Anthropic rejects it with 400
  5. Error repeats on every subsequent turn - session permanently bricked

Secondary Issue (Non-blocking follow-up)

src/agents/anthropic-transport-stream.ts:1125 does not set a display field when initializing thinking blocks, while src/llm/providers/anthropic.ts:987 sets display: "summarized".

Note: After analysis, this is a separate concern from the signature corruption bug:

  • display is a request-level parameter (params.thinking.display), not a content block field
  • The TransportContentBlock type does not include a display field
  • Its absence does not affect signature integrity or replay correctness
  • It may affect thinking behavior on newer models (Opus 4.7 / Mythos Preview) that support adaptive thinking
  • This should be tracked as a separate follow-up, not a blocker for the signature fix

Recovery for Already-Corrupted Sessions

Existing sessions with truncated signatures are handled by wrapAnthropicStreamWithRecovery (thinking.ts:482):

  1. Corrupted session replays truncated signature → Anthropic returns 400
  2. THINKING_BLOCK_ERROR_PATTERN matches the error message
  3. Recovery strips ALL thinking blocks from the message history
  4. Retry succeeds without thinking blocks → session continues normally
  5. New responses store correct signatures going forward

Users do NOT need to /reset — the recovery mechanism handles this automatically on the next request.

Real-World Observation

Observed on a production Mac Mini gateway (OpenClaw 0.6.0-dev) with claude-opus-4-6:

  • Session with thinking enabled produces assistant message with thinking blocks
  • After a few turns, every subsequent request fails with the 400 thinking block error
  • Session permanently stuck until /reset
  • Gateway logs show repeated embedded run failover decision: decision=surface_error reason=format

Related Issues

  • #80625 - Same symptom (permanent session corruption from thinking blocks), suggests strip-on-persist as fix. Our finding shows the actual root cause is upstream in the streaming layer, not in persistence.
  • #85781 - "Claude signed thinking blocks can still poison session replay" - P1 maintainer issue. The replay policy discussion is relevant but the root cause is the malformed signature from transport stream, not the replay policy.
  • #87475 - "Filter noisy invalid_request_error subtypes" - Reports the same Invalid signature in thinking block error reaching users. The wrapAnthropicStreamWithRecovery (#86886) single-retry cannot help because the signature is fundamentally truncated at storage time.
  • #87329 - Subagent echo messages with wrong provider metadata amplify the same thinking-block 400 error after gateway restart.

Why Existing Fixes Are Insufficient

  • #86886 wrapAnthropicStreamWithRecovery: Provides one-shot recovery (strip thinking + retry), but cannot prevent corruption from recurring on every new thinking response. The root cause fix is needed to stop new signatures from being truncated.
  • Session file repair (session file repaired: rewrote N assistant messages): Does not reconstruct the correct signature (impossible without re-streaming from Anthropic).
  • dropThinkingBlocks replay policy: Only helps non-native routes (Copilot). Native Anthropic routes need valid signatures for continuity.

Fix

// src/agents/anthropic-transport-stream.ts:1289
// Before:
block.thinkingSignature = delta.signature;

// After:
block.thinkingSignature = (block.thinkingSignature || "") + delta.signature;

Acceptance Criteria

  • signature_delta chunks are concatenated, not overwritten
  • Sessions with thinking enabled can survive multiple turns without 400 errors
  • Existing tests for thinking block handling pass
  • Real-scenario proof demonstrates the patched code path correctly concatenates signatures

Non-blocking Follow-up

  • Transport thinking display parameter alignment (separate from content block storage; does not affect signature integrity)

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING