Fix pending tool result causing Anthropic API contract violation on runtime restart#4315
Fix pending tool result causing Anthropic API contract violation on runtime restart#4315alco wants to merge 2 commits into
Conversation
❌ 1 Tests Failed:
View the top 1 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
Claude Code ReviewSummaryNo code changes since iteration 1 — the two commits were recommitted on 2026-05-18 but the diff is identical. The original review still stands; the critical test-failure issue is now confirmed by codecov on this PR. What's Working Well(Unchanged from iteration 1.)
Issues FoundCritical (Must Fix)Existing test still fails on this branchFile:
Important (Should Fix)No positive test for the new branch across non-terminal statuses
Suggestions (Nice to Have)Comment is slightly misleading
// Runtime interrupted before the tool reached a terminal state.
// Synthesize an error result so Anthropic's tool_use/tool_result pairing holds.Follow-up: converge the persisted row to a terminal stateThe synthetic error is regenerated on every wake; the persisted row never moves to Issue ConformanceNo linked issue. PR description is self-contained and accurately captures the bug, including the exact Anthropic error string and reproduction scenario. Previous Review Status
Review iteration: 2 | 2026-05-18 |
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6fd6acd to
113584d
Compare
Summary
When the agent runtime is interrupted mid-tool-execution (e.g. desktop app crash), the tool call is persisted to the timeline with a non-terminal status (
started,args_complete, orexecuting) but notool_resultis ever written. On the next wake,defaultProjectionintimeline-context.tsemits thetool_callmessage but skips thetool_resultbecause it only emits one forcompleted/failedstatuses. The resulting message history sent to Anthropic violates the API contract that everytool_useblock must be followed by a matchingtool_result, and the API rejects the request with:This puts the agent into a permanent error loop — every subsequent wake replays the same broken history and fails identically.
Fix
Synthesize an error
tool_resultfor any tool call that is not in a terminal state. The result's content notes that the tool was interrupted and includes the last-known status, so the model can see what happened and proceed instead of being trapped.This is the smallest change that restores API compliance and lets a crashed agent recover on its own.
Test plan
bashtool execution and confirm the agent recovers on next wake instead of looping on400 invalid_request_error🤖 Generated with Claude Code