anomalyco / anomalyco/opencode
Phantom tool call in an extended-thinking turn permanently wedges the session
@neriousy is already working on this.
Since Sep 4, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
What happens
When a model calls a nonexistent tool during an extended-thinking turn, opencode stores it as an invalid tool part. On the next request that turn is the latest assistant message, and Anthropic rejects every continuation:
messages.N.content.M: `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.
The session is stuck for good. Only editing storage or starting fresh recovers it.
Why
toModelMessagesEffect (packages/opencode/src/session/message-v2.ts) replays invalid tool parts as normal tool_use/tool_result blocks. They land interleaved between the signed thinking blocks, which breaks the byte-exact thinking replay Anthropic validates. The phantom call was never executed, so replaying it adds nothing but breakage (and re-injects the full tool list, see #41047).
Repro
- Anthropic/Bedrock model, extended thinking on.
- One turn calls a tool that does not exist (happens with some models / MCP setups).
- Continue the session -> permanent 400, "thinking blocks cannot be modified".
Fix
Drop invalid tool parts when building model messages; thinking blocks stay intact. PR incoming.
Related: #39291, #41738, #31188 (compaction variants of the same class), #41047, #33618 (phantom tool calls).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.