anomalyco / anomalyco/opencode

V2: errored-message replay can 400 with Anthropic thinking + tool use

Open
#38,620 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug core
Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Problem

In the V2 session core, replaying history that contains an errored assistant message can produce a request Anthropic rejects with a 400 when extended thinking is enabled.

reuseProviderMetadata requires message.error === undefined (packages/core/src/session/runner/to-llm-message.ts:114), so an aborted/failed step drops all reasoning state on replay — both signed thinking (anthropic.signature) and redacted thinking (anthropic.redactedData) — while still replaying that same message's tool_use parts.

Anthropic requires a tool_use block to be preceded by its thinking/redacted_thinking block when thinking is enabled. Replaying tool_use without the reasoning block yields a 400 from the API.

Impact

Multi-turn thinking + tool-use conversations with Anthropic break after an interrupt or failure mid-step: the follow-up request replays the errored message's tool calls stripped of their reasoning blocks and the provider rejects it.

Scope

  • Pre-existing behavior; unrelated to and not introduced by #38614 (which added redacted thinking round-trip support in packages/ai). Signed thinking is affected identically.
  • The errored-message guard is otherwise a deliberate design decision, so the fix should be deliberate too.

Possible directions

  • Relax the message.error === undefined guard in to-llm-message.ts so reasoning provider state is reused for errored messages when provider+model match, or
  • Drop the errored message's tool-call parts alongside the reasoning so the replayed message stays self-consistent (no orphaned tool_use).

Either way, the invariant to preserve is: never replay a tool_use part to Anthropic without its preceding thinking block while thinking is enabled.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/core/src/session/runner/to-llm-message.ts around line 114 and trace how reuseProviderMetadata handles errored messages during V2 history replay. Compare the two proposed directions and verify the resulting replay preserves Anthropic's invariant: a tool_use part is never sent without its preceding thinking or redacted_thinking block when thinking is enabled.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
ai, backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.