Escape (cancel) does not kill in-flight parallel tool calls, causing repeated auto-resume
Bug Description
When the user presses Escape to cancel/stop Claude during execution of parallel tool calls, the onCancel event fires and the current API stream is aborted — but already-dispatched parallel tool calls continue running. When those tool results return, Claude Code automatically starts a new API turn, effectively ignoring the user's cancel.
This forces the user to press Escape repeatedly (5+ times in my case) to kill each successive auto-resumed turn, creating a frustrating experience where it feels like cancel is completely broken.
Steps to Reproduce
- Give Claude a task that triggers multiple parallel tool calls (e.g., 3 parallel SSH commands)
- While the tools are executing, press Escape
- Observe: the current API stream aborts, but the parallel tools keep running
- When a parallel tool result returns, a new API turn starts automatically
- User must press Escape again to kill the new turn
- Repeat until all in-flight tools have returned
Expected Behavior
Pressing Escape should:
- Abort the current API stream (✅ this works)
- Kill/cancel ALL in-flight parallel tool calls (❌ this does NOT happen)
- NOT auto-start a new API turn from returned tool results after cancel (❌ this does NOT happen)
Actual Behavior
Escape only aborts the current stream. Parallel tools continue, their results trigger new API turns, and the model keeps generating responses and new tool calls.
Debug Log Evidence
From session debug log, the cancel/resume cycle is clearly visible:
06:24:35.377Z [DEBUG] Stream started - received first chunk ← parallel streams running
06:24:35.455Z [DEBUG] [onCancel] focusedInputDialog=undefined ← user presses Escape
06:24:35.456Z [ERROR] API error: Request was aborted. ← stream aborted (good)
06:24:36.155Z [DEBUG] attribution header ... ← 600ms later, NEW API request
06:24:36.156Z [DEBUG] [API:request] Creating client... ← auto-resumed from tool result
This pattern repeated multiple times in a single session, with the user pressing Escape 5+ times and typing "STOP" in chat, unable to halt execution.
Environment
- Claude Code version: 2.1.47
- OS: macOS (Darwin 25.3.0)
- Model: claude-opus-4-6
Impact
This is a significant UX issue. Escape is the user's only kill switch. When it doesn't work, the user has no way to stop Claude from continuing to execute commands — including potentially destructive server operations. In this session, SSH commands continued executing on a production server after the user repeatedly tried to cancel.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗