-
-
Notifications
You must be signed in to change notification settings - Fork 79.1k
Anthropic thinking blocks rejected after sanitizeTransportPayloadText() mutates signed content #87459
Copy link
Copy link
Closed
Labels
P1High-priority user-facing bug, regression, or broken workflow.High-priority user-facing bug, regression, or broken workflow.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.ClawSweeper found a clear likely implementation shape for this issue.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.ClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.ClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.Auth, provider routing, model choice, or SecretRef resolution may break.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.Session, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.
Metadata
Metadata
Assignees
Labels
P1High-priority user-facing bug, regression, or broken workflow.High-priority user-facing bug, regression, or broken workflow.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.ClawSweeper found a clear likely implementation shape for this issue.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.ClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.ClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.Auth, provider routing, model choice, or SecretRef resolution may break.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.Session, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.
Type
Fields
Give feedbackNo fields configured for issues without a type.
Bug: Anthropic thinking blocks rejected after sanitizeTransportPayloadText() mutation
Reporter: Bryan Baer (cerebral.baerautotech.com)
Date: 2026-05-27
OpenClaw version: 2026.5.26
Severity: High — blocks all long-running sessions on Anthropic models when thinking is enabled
Summary
provider-stream-DRIaVJMo.jsappliessanitizeTransportPayloadText()to the content of Anthropic-signedthinkingblocks while preserving the originalthinkingSignature. The sanitizer strips orphan UTF-16 surrogate halves, mutating the text. Anthropic's API rejects the next turn because the mutated text no longer matches the cryptographic signature it issued in the prior response.Symptoms
API error from Anthropic:
Where N is the offending message index (typically 100+ in long sessions) and M is the offending content block index.
Reproduction
claude-sonnet-4-6,claude-opus-4-7)Affects:
Root Cause
File:
src/agents/provider-stream.ts(compiled todist/provider-stream-DRIaVJMo.js)Lines: ~301–322 (compiled)
sanitizeTransportPayloadText(inopenai-transport-stream-DNhzccm-.js):This regex strips lone surrogates. It also strips characters during multi-codepoint normalization edge cases if any prior stage has touched the text.
The signature attached by Anthropic is computed against the EXACT byte representation Anthropic returned. ANY mutation to the text breaks the signature, even removing characters that "look" invalid to OpenAI-style transports.
Why this is wrong for Anthropic specifically
The OpenAI/Azure-OpenAI transport requires
sanitizeTransportPayloadTextbecause their Responses API rejects messages containing orphan surrogates. Anthropic does not have this constraint — they happily round-trip their own response data byte-for-byte. The sanitizer should only run for transports that need it, and never for content whose integrity is signed by the provider.The
reasoning_contentsignature variant is a synthetic value OpenClaw assigns to non-Anthropic reasoning (e.g. xAI Grok, DeepSeek). Those signatures are not cryptographic — they're just markers. Sanitizing those is fine.Fix
if (block.type === "thinking") { if (block.redacted) { /* ... */ } if (block.thinking.trim().length === 0) continue; if (!block.thinkingSignature || block.thinkingSignature.trim().length === 0) { blocks.push({ type: "text", text: sanitizeTransportPayloadText(block.thinking) }); } else { - const thinking = sanitizeTransportPayloadText(block.thinking); + // Do NOT sanitize Anthropic-signed thinking blocks. Sanitization mutates + // the text and invalidates the cryptographic signature attached by Anthropic. + // Only sanitize the synthetic "reasoning_content" signature variant. + const thinking = block.thinkingSignature === "reasoning_content" + ? sanitizeTransportPayloadText(block.thinking) + : block.thinking; if (block.thinkingSignature === "reasoning_content") { // ... } blocks.push({ type: "thinking", thinking, signature: block.thinkingSignature }); } }Impact (in our deployment)
Today's session (4-hour registry migration with parallel Sonnet subagents):
This is blocking real production work on platforms relying on OpenClaw + Anthropic.
Suggested test case
Workaround (applied locally)
Patched
dist/provider-stream-DRIaVJMo.jsdirectly with the fix above. Backup of original atdist/provider-stream-DRIaVJMo.js.bak-pre-thinking-sig-fix.I'm happy to submit this as a PR to the upstream repo. Let me know if you want any additional diagnostic data (sample failing message, stack trace, etc.) attached.