[Fix] Bug fix for API 400 error "`tool_use` ids must be unique"
Status Closed — not planned
Reported on v2.0.76
Maintainer reply None cached
Activity 4 comments · opened Jan 24, 2026 · closed Feb 28, 2026
Bug Description
(This is for v.2.0.76, but v.2.1.19 has exactly the same bug)
The QS function (line 482734) is supposed to slice messages from a compaction boundary:
function QS(A) {
let Q = I97(A);
if (Q === -1) return A; // BUG: Returns same reference!
return A.slice(Q);
}
I97 searches for compact_boundary messages. When there's no compaction:
- I97 returns -1
- QS returns
Adirectly without creating a copy
How This Causes Duplication
- qe2 starts with
mA = [...V](copy of mutableMessages) - qe2 calls
ew({ messages: mA }) - ew creates
F = QS(mA)- butF === mA(same reference!) - ew makes API call, receives streaming response
- Streaming yields partial message P1 (with tool_use)
- ew accumulates P1:
L.push(P1), yields P1 - qe2 receives P1:
mA.push(P1)- mA now has P1, and since F === mA, F also has P1! - ew recursively calls itself with:
``javascript``
yield* ew({
messages: [...F, ...L, ...N],
});
- At this point:
- F = mA = [original..., P1, ...]
- L = [P1, ...]
- P1 appears in BOTH F and L!
- Inner ew -> zHA -> SW9 -> GJ normalizes messages
- GJ finds two messages with same
message.id, merges with e27 - e27 concatenates content arrays: duplicate tool_use blocks!
Proposed Fix
// Before
if (Q === -1) return A;
// After
if (Q === -1) return [...A];
One-character fix: always return a copy!
Environment Info
- Platform: linux
- Terminal: kitty
- Version: 2.0.76
- Feedback ID: 82a1446e-9fb5-4c89-8018-1e45ea46dde1
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗