Skip to content

fix(session): drop duplicate tool results in sanitizeToolCalls#3162

Open
Sayt-0 wants to merge 1 commit into
mainfrom
fix/1593-duplicate-tool-result
Open

fix(session): drop duplicate tool results in sanitizeToolCalls#3162
Sayt-0 wants to merge 1 commit into
mainfrom
fix/1593-duplicate-tool-result

Conversation

@Sayt-0

@Sayt-0 Sayt-0 commented Jun 18, 2026

Copy link
Copy Markdown
Member

TL;DR

Context

AWS Bedrock rejects any turn whose toolResult blocks outnumber the previous turn's toolUse blocks:

The number of toolResult blocks ... exceeds the number of toolUse blocks of previous turn.

Known structural causes and coverage:

Cause Handled by Status
Result with no matching tool_use (orphan) sanitizeToolCalls (#3001) covered
Result for a tool_use that never produced one (missing) placeholder injection (#3001) covered
Second result for the same tool_call_id (duplicate) this PR new

Change

Test

  • TestSanitizeToolCalls_DropsDuplicateToolResult (new)
  • existing sanitize / orphan tests still pass

Notes

  • Duplicates can surface from provider or streaming quirks (tool-call deltas re-emitting an id), so this completes the guard rather than fixing a confirmed in-the-wild trigger.

sanitizeToolCalls already drops orphaned tool results and injects
placeholders for missing ones so toolUse/toolResult stays balanced for
strict providers like AWS Bedrock. It did not cover a second tool_result
carrying the same tool_call_id: that leaves more toolResult than toolUse
blocks and triggers the same ValidationException ("the number of
toolResult blocks ... exceeds the number of toolUse blocks of previous
turn") as the orphaned-result case behind #1676 and #1593.

Keep only the first result per tool_use and drop later duplicates.
@Sayt-0 Sayt-0 requested a review from a team as a code owner June 18, 2026 09:38

@docker-agent docker-agent left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment: 🟢 APPROVE

The change is correct and well-scoped. sanitizeToolCalls now drops duplicate tool_result messages for the same tool_call_id before the request reaches the provider, closing the last known structural cause of AWS Bedrock's toolResult/toolUse count mismatch (ValidationException).

Production logic (session.go): The new guard is placed after the existing orphan check and before resultIDs is updated, so it fires exactly when a second result for the same tool_call_id arrives within the same pending group. flushPending resets both maps, so the guard is naturally scoped to each turn — cross-turn duplicates are already handled as orphans. No logic errors found.

Test (sanitize_orphan_test.go): TestSanitizeToolCalls_DropsDuplicateToolResult exercises the new path end-to-end. The explicit count != 1 assertion is the right guard for this case. The assertToolPairingInvariant helper is appropriately scoped to orphan detection and the test compensates for its narrower scope with the direct count check.

No issues found in the changed code.

@aheritier aheritier added area/runtime Runtime engine, agent loop execution, tool dispatch, loop detection area/sessions For features/issues/fixes related to session lifecycle (resume, persistence, export) kind/fix PR fixes a bug (maps to fix: commit prefix) labels Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/runtime Runtime engine, agent loop execution, tool dispatch, loop detection area/sessions For features/issues/fixes related to session lifecycle (resume, persistence, export) kind/fix PR fixes a bug (maps to fix: commit prefix)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants