anomalyco / anomalyco/opencode
Compaction permanently fails with 'Duplicate value for tool_call_id' after an interrupted tool run
@rekram1-node is already working on this.
Since Aug 3, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
An aborted/interrupted tool run leaves a second tool part with the same callID in the message. The next auto-compaction then re-sends the full history to the provider and fails with 400 invalid_request_error: Duplicate value for 'tool_call_id', so compaction never completes (summary never written, token counter never resets). The session is effectively poisoned — every subsequent compaction fails the same way.
Root cause evidence (local sqlite DB, opencode v1.18.11)
One assistant message contains two tool parts sharing the same callID: a completed one (tool=todowrite) and an error one (tool=unknown, error: "Tool execution aborted", metadata.interrupted: true).
Message msg_fb9813f84... (session ses_0507e87b...):
- part
prt_fb9814a85...:{"type":"tool","tool":"todowrite","callID":"functions.todowrite:1","state":{"status":"completed",...}} - part
prt_fb9816675...:{"type":"tool","tool":"unknown","callID":"functions.todowrite:1","state":{"status":"error","input":{},"raw":"","error":"Tool execution aborted","metadata":{"interrupted":true},...}}
Message msg_fc35e22d5... (same session):
- part
prt_fc35e5d6d...:{"type":"tool","tool":"todowrite","callID":"functions.todowrite:0","state":{"status":"completed",...}} - part
prt_fc35e7502...:{"type":"tool","tool":"unknown","callID":"functions.todowrite:0","state":{"status":"error","input":{},"raw":"","error":"Tool execution aborted","metadata":{"interrupted":true},...}}
The unknown part with Tool execution aborted is written when a run is interrupted; it duplicates the callID of the tool call that was already recorded as completed.
Failure symptom
Two consecutive auto-compactions in the same session failed identically:
msg_fb9e6c8bf...(compaction, finish=None, err=true):
Error from provider (DeepSeek): Duplicate value for 'tool_call_id' of functions.todowrite:1 in message[53](400)msg_fc45786f2...(compaction, finish=None, err=true):
Error from provider (Console): Upstream request failed: [invalid_request_error] Duplicate value for 'tool_call_id' of functions.todowrite:0 in message[224](400)
Log excerpt:
timestamp=...T21:18:22.176Z level=ERROR ... agent=compaction mode=primary
error.error="AI_APICallError: Error from provider (Console): Upstream request failed: [invalid_request_error] Duplicate value for 'tool_call_id' of functions.todowrite:0 in message[224]"
Because compaction serializes the entire history head to the model, the duplicate is always present → compaction aborts before producing a summary → the message count / token counter keep growing and the session never recovers, even though compaction.auto and prune are enabled.
Expected behavior
- Tool parts must be deduplicated by
callIDbefore building model messages (drop theunknown/interrupted duplicate, keep thecompletedone), or - interrupted runs should not write a second tool part with an existing
callIDat all.
Impact
Sessions that suffer an interrupted tool run become permanently un-compactable (until a fresh session). Auto-compaction then loops on the same 400, the token counter stays high, and the user is forced to /new.
Repro notes / workaround
- Took the evidence from
~/.local/share/opencode/opencode.db(tablesmessage,part; parts of typetoolwith duplicatecallIDwhere one istool="unknown",error="Tool execution aborted"). - Workaround for the affected session: delete the duplicate
unknown/interrupted tool part (keep thecompletedone) while opencode is closed.
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.