fix: prevent synthetic toolResult for aborted/errored assistant messages

When an assistant message with toolCalls has stopReason 'aborted' or 'error',
the guard should not add those tool call IDs to the pending map. Creating
synthetic tool results for incomplete/aborted tool calls causes API 400 errors:
'unexpected tool_use_id found in tool_result blocks'

This aligns the WRITE path (session-tool-result-guard.ts) with the READ path
(session-transcript-repair.ts) which already skips aborted messages.

Fixes: orphaned tool_result causing session corruption

Tests added:
- does NOT create synthetic toolResult for aborted assistant messages
- does NOT create synthetic toolResult for errored assistant messages
This commit is contained in:
Leakim
2026-02-24 13:15:38 +00:00
committed by Peter Steinberger
parent 31b1b20b3c
commit 8db7ca8c02
2 changed files with 67 additions and 1 deletions

View File

@@ -166,8 +166,15 @@ export function installSessionToolResultGuard(
return originalAppend(persisted as never);
}
// Skip tool call extraction for aborted/errored assistant messages.
// When stopReason is "error" or "aborted", the tool_use blocks may be incomplete
// and should not have synthetic tool_results created. Creating synthetic results
// for incomplete tool calls causes API 400 errors:
// "unexpected tool_use_id found in tool_result blocks"
// This matches the behavior in repairToolUseResultPairing (session-transcript-repair.ts)
const stopReason = (nextMessage as { stopReason?: string }).stopReason;
const toolCalls =
nextRole === "assistant"
nextRole === "assistant" && stopReason !== "aborted" && stopReason !== "error"
? extractToolCallsFromAssistant(nextMessage as Extract<AgentMessage, { role: "assistant" }>)
: [];