Skip to content

[Bug]: wrapAnthropicStreamWithRecovery bypassed when streamFn is async (embedded agent path) #95429

Description

@alexelgier

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

OpenClaw’s thinking-signature auto-recovery never runs on the embedded agent path because wrapEmbeddedAgentStreamFn returns an async Promise, so wrapAnthropicStreamWithRecovery skips pumpStreamWithRecovery and only handles Promise rejections. Anthropic replay errors arrive as stream {type:"error"} events after the Promise resolves, so the session bricks with a misleading “schema or tool payload” error until /new or manual transcript repair.

Steps to reproduce

  1. Run OpenClaw 2026.6.8 gateway with embedded agent on Anthropic claude-sonnet-4-6 with extended thinking enabled (thinking=adaptive at gateway startup; session transcript recorded thinkingLevel: high).
  2. Start a fresh main session (/new) via webchat (OpenClaw Windows Tray → WSL2 gateway).
  3. Have a multi-turn conversation that produces at least one assistant reply with a signed thinking block (extended thinking).
  4. Trigger a thinking-signature replay failure on the next user message. In our case this happened naturally: assistant message 1c035d3e was persisted with a corrupted thinkingSignature containing literal *** (invalid base64), causing Anthropic to reject replay.
  5. Send another user message in the same session.
  6. Observe the turn fails immediately (~500ms).
  7. Retry the same message 2–3 times — each attempt fails identically.
  8. Check gateway logs for [session-recovery] — none appear.

Minimal architectural repro (code path):

Embedded agent uses resolveEmbeddedAgentStreamFn() → wrapEmbeddedAgentStreamFn() (returns async stream function).
wrapAnthropicStreamWithRecovery() is applied afterward.
When Anthropic rejects replay, the provider emits { type: "error" } on the stream after the async Promise has already resolved — recovery's pumpStreamWithRecovery() never runs.

Expected behavior

Per docs/reference/transcript-hygiene.md and wrapAnthropicStreamWithRecovery in dist/compaction-successor-transcript-*.js:

Detect Anthropic thinking replay errors matching Invalid signature in thinking block.
Log e.g. [session-recovery] Anthropic thinking request rejected; retrying once without thinking blocks.
Retry once with stripAllThinkingBlocks(originalMessages).
On successful retry, persist transcript repair via repairRejectedThinkingReplayInSessionManager().
User-facing error for providerRuntimeFailureKind: "replay_invalid" should indicate invalid session replay (docs suggest /new), not a generic schema rejection.

Actual behavior

Every subsequent message in the session fails with:
LLM request failed: provider rejected the request schema or tool payload.
Raw provider error (classified internally as replay_invalid):
messages.3.content.0: Invalid signature in thinking block
No [session-recovery] log lines anywhere in gateway journal or /tmp/openclaw/openclaw-*.log.
Retries do not self-heal; session stays broken until /new or manual transcript repair.
Misleading user-facing message: internal classification is replay_invalid, but UI shows schema/tool-payload rejection because invalid_request_error triggers PROVIDER_SCHEMA_REJECTION_USER_TEXT.

OpenClaw version

2026.6.8

Operating system

Windows

Install method

No response

Model

anthropic/claude-sonnet-4-6

Provider / routing chain

OpenClaw Windows Tray (webchat/cli) → OpenClaw gateway (local, loopback :18789) → embedded agent runner (agent:main:main) → stream strategy: boundary-aware:anthropic-messages → wrapEmbeddedAgentStreamFn (async, resolves API key) → wrapAnthropicStreamWithRecovery (broken Promise branch) → Anthropic Messages API (direct, api.anthropic.com) → model: claude-sonnet-4-6

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Jun 20 23:43:48 [agent/embedded] embedded run agent end: runId=8e995473-...
  isError=true model=claude-sonnet-4-6 provider=anthropic
  error=LLM request failed: provider rejected the request schema or tool payload.
  rawError={"type":"error","error":{"type":"invalid_request_error",
    "message":"messages.3.content.0: Invalid `signature` in `thinking` block"},...}
  providerRuntimeFailureKind=replay_invalid
Jun 20 23:44:23  (same error, runId=3ee81255-...)
Jun 20 23:44:40  (same error, runId=c196e216-...)

Impact and severity

Severity: High (session-bricking, no auto-recovery, misleading error)

Any session with a bad thinking signature replay enters a permanent failure loop until /new or manual .jsonl repair.
User sees misleading “schema or tool payload” error instead of “invalid session replay — use /new”.
Documented auto-recovery ([session-recovery]) never runs on the embedded agent path, which is the primary gateway/webchat path.
Retries waste API calls and confuse users (we hit the same error 3× in ~1 minute).

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.bugSomething isn't workingbug:behaviorIncorrect behavior without a crashclawsweeper:linked-pr-openClawSweeper 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:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, 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.

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions