Description
RunnerContextImpl.executeSequentially/executeParallel's tool-call path (ToolCallAction.java:256) catches InterruptedException the same as any ordinary tool failure, records it as a tool error, and lets the action loop continue — unlike the chat-call path (fixed in #1071), which now rethrows a raw InterruptedException immediately.
Concretely, on a cancellation during a tool call:
ToolCallAction.java:256 catches the InterruptedException, :257 records it as a tool error.
- The loop moves on and (
:85) sends the ToolResponseEvent anyway, which drives another chat call.
ActionExecutionOperator then persists the action as completed (~line 491, durableExecManager.maybePersistTaskResult), since nothing tells it the action was actually interrupted.
- On recovery,
actionState.isCompleted() (~line 437) skips re-execution and replays that stale output instead of re-running the call.
Step 4 is the same failure mode as #1070's "problem 2" (a stale interruption replayed as terminal after recovery), just reached through the action-state persistence path instead of the durable-call-slot path that #1071 closed for the chat side — because here the raw InterruptedException never escapes far enough to skip the persist call.
executeParallel has the equivalent shape at RunnerContextImpl.java:209 (parallel tool call execution added in #926).
This predates #1071 and is out of that PR's scope (chat-call retry/persistence only); filing separately per discussion on #1071 (comment) and follow-up at #1071 (comment).
Expected behavior
A cancellation during a tool call should propagate the same way the chat-call fix in #1071 does: restore the interrupt flag and rethrow immediately, rather than being recorded as a tool error and let the action loop continue — so the action is never persisted as completed off the back of a cancelled tool call, and recovery re-executes rather than replaying stale output.
Are you willing to submit a PR?
Description
RunnerContextImpl.executeSequentially/executeParallel's tool-call path (ToolCallAction.java:256) catchesInterruptedExceptionthe same as any ordinary tool failure, records it as a tool error, and lets the action loop continue — unlike the chat-call path (fixed in #1071), which now rethrows a rawInterruptedExceptionimmediately.Concretely, on a cancellation during a tool call:
ToolCallAction.java:256catches theInterruptedException,:257records it as a tool error.:85) sends theToolResponseEventanyway, which drives another chat call.ActionExecutionOperatorthen persists the action as completed (~line 491,durableExecManager.maybePersistTaskResult), since nothing tells it the action was actually interrupted.actionState.isCompleted()(~line 437) skips re-execution and replays that stale output instead of re-running the call.Step 4 is the same failure mode as #1070's "problem 2" (a stale interruption replayed as terminal after recovery), just reached through the action-state persistence path instead of the durable-call-slot path that #1071 closed for the chat side — because here the raw
InterruptedExceptionnever escapes far enough to skip the persist call.executeParallelhas the equivalent shape atRunnerContextImpl.java:209(parallel tool call execution added in #926).This predates #1071 and is out of that PR's scope (chat-call retry/persistence only); filing separately per discussion on #1071 (comment) and follow-up at #1071 (comment).
Expected behavior
A cancellation during a tool call should propagate the same way the chat-call fix in #1071 does: restore the interrupt flag and rethrow immediately, rather than being recorded as a tool error and let the action loop continue — so the action is never persisted as completed off the back of a cancelled tool call, and recovery re-executes rather than replaying stale output.
Are you willing to submit a PR?