You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix: prevent tool executions from hanging indefinitely - #54297
A tool execution that never settles (reported for
ead\ in #53433) blocks the session step forever: the runner awaits tool settlements via FiberSet join with no deadline, and the registry invoked leaf tools with no timeout.
The fix puts one shared absolute deadline (\DEFAULT_TOOL_TIMEOUT_MS = 5 min) at \ToolRegistry.settleWith, the only settlement boundary, instead of a timer in every tool. On expiry the leaf fiber is interrupted via \Effect.timeoutOption\ and the timeout becomes an ordinary error-result settlement, so it flows through the existing \Tool.Failed\ lifecycle and a late leaf result can never overwrite it. Per-tool override via \Tool.make({ timeoutMs }): \�ash\ opts out (owns its own timeout, up to 10 min) and \question\ opts out (waits on the user). MCP tools inherit the same policy through this path; Code Mode keeps its existing timeout behavior.
\�un test test/session-runner-tool-registry.test.ts test/tool-question.test.ts test/application-tools.test.ts test/tool-output-store.test.ts\ in packages/core: 46 pass, 0 fail, including new regression tests for a never-settling tool and for late completion after timeout.
\�un run typecheck\ in packages/core: exit 0.
\git diff --check: clean.
Note: permission-approval waits inside non-\question\ tools are now also bounded by the 5 min default.
Thanks for digging into this and for adding regression tests, @shaiktabrez0204-droid!
The dev branch (v1) only takes critical fixes, such as data loss, security problems or breakage with no workaround. A tool call that never finishes can be recovered by interrupting the session, as #53433 notes. This change also adds a new feature, a default timeout for every tool, so it doesn't fit v1.
Work on tool timeouts belongs on the v2 branch (see also #54220). The code there is laid out differently (there's no packages/core/src/tool/registry.ts), so the change would need redoing against v2 if you'd like to open a pull request there.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue for this PR
Closes #53433
Type of change
What does this PR do?
A tool execution that never settles (reported for
ead\ in #53433) blocks the session step forever: the runner awaits tool settlements via FiberSet join with no deadline, and the registry invoked leaf tools with no timeout.
The fix puts one shared absolute deadline (\DEFAULT_TOOL_TIMEOUT_MS = 5 min) at \ToolRegistry.settleWith, the only settlement boundary, instead of a timer in every tool. On expiry the leaf fiber is interrupted via \Effect.timeoutOption\ and the timeout becomes an ordinary error-result settlement, so it flows through the existing \Tool.Failed\ lifecycle and a late leaf result can never overwrite it. Per-tool override via \Tool.make({ timeoutMs }): \�ash\ opts out (owns its own timeout, up to 10 min) and \question\ opts out (waits on the user). MCP tools inherit the same policy through this path; Code Mode keeps its existing timeout behavior.
Related: #54220
How did you verify your code works?
Note: permission-approval waits inside non-\question\ tools are now also bounded by the 5 min default.
Screenshots / recordings
Not a UI change.
Checklist