Skip to content

fix: guard postToolUse hook against closed response stream (fixes #319003)#319011

Open
vs-code-engineering[bot] wants to merge 2 commits into
mainfrom
fix/stream-closed-post-hook-319003-f59c7075aade6723
Open

fix: guard postToolUse hook against closed response stream (fixes #319003)#319011
vs-code-engineering[bot] wants to merge 2 commits into
mainfrom
fix/stream-closed-post-hook-319003-f59c7075aade6723

Conversation

@vs-code-engineering
Copy link
Copy Markdown
Contributor

@vs-code-engineering vs-code-engineering Bot commented May 29, 2026

Summary

The Copilot Chat extension throws an unhandled error "Response stream has been closed" when the postToolUse hook completes after the response stream has already been closed (e.g., due to user cancellation). This affects 158 users with 1,096 hits on extension version 0.50.0 (Windows). The fix adds a cancellation token guard before executing the postToolUse hook.

Fixes #319003
Recommended reviewer: @pwang347

Culprit Commit

Field Value
Commit Not identified — pre-existing race condition
Why The race between stream closure and async hook completion has existed since hooks were moved to the extension in Feb 2026. The bucket appeared with 0.50.0, likely due to increased hook usage or timing changes.

Code Flow

sequenceDiagram
    participant TC as toolCalling.tsx
    participant CHS as chatHookService.ts
    participant HRP as hookResultProcessor.ts
    participant Stream as extHostChatAgents2.ts

    TC->>CHS: executePostToolUseHook(stream)
    Note over Stream: User cancels request
    Stream-->>Stream: _isClosed = true
    CHS->>HRP: processHookResults(outputStream)
    HRP->>Stream: hookProgress(warnings)
    Stream-->>HRP: throws Error Response stream has been closed
Loading

Affected Files

File Role
extensions/copilot/src/extension/prompts/node/panel/toolCalling.tsx Caller that invokes postToolUse hook with stream reference
extensions/copilot/src/extension/intents/node/hookResultProcessor.ts Crash site — calls hookProgress on closed stream
extensions/copilot/src/extension/chat/vscode-node/chatHookService.ts Hook execution orchestrator
src/vs/workbench/api/common/extHostChatAgents2.ts Throws the error when stream is closed

Repro Steps

  1. Start a Copilot Chat conversation that triggers tool use with hooks configured
  2. Cancel the request (or let it timeout) while a tool is executing
  3. The postToolUse hook completes and tries to write warnings to the now-closed stream
  4. "Response stream has been closed" error is thrown and reaches telemetry

How the Fix Works

Chosen approach (extensions/copilot/src/extension/prompts/node/panel/toolCalling.tsx): Added a guard clause if (props.token.isCancellationRequested) { return; } before calling executePostToolUseHook. This prevents the hook from executing when the request is already cancelled, which means the stream is closed and cannot accept output. This fixes at the data producer level — the producer of the "stream write after close" scenario is the code that initiates the hook call without checking whether the stream is still writable.

Alternatives considered: Adding try/catch around hookProgress calls in hookResultProcessor.ts — rejected because it masks errors at the crash site rather than preventing the invalid operation upstream, and violates the principle of never silencing errors with try/catch.

Recommended Owner

@pwang347 — owns Chat Hooks area per working-areas.md, active contributor (committed today).

errors-fix-driver — cycle 1

Trigger: cron_check_failed · Head: 6c24c8028b6

Item Action
CI: Compile & Hygiene (real) Fixed — unicode em-dash (U+2014) in comment replaced with ASCII hyphen

Push: yes — 6c24c8028b6 · Copilot rerequested: ok

Ready gate: ci pending (new push) → not marking ready this cycle

Generated by errors-fix · ● 86.3M ·

Generated by errors-fix-driver · ● 34.7M ·

…9003)

When the user cancels a chat request while tools are executing, the
response stream is closed. The postToolUse hook would then attempt to
write warnings via hookProgress to the closed stream, causing an
unhandled 'Response stream has been closed' error.

Add a cancellation token check before executing the postToolUse hook.
If the request is already cancelled, skip the hook entirely since the
stream cannot accept further output.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 29, 2026 16:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@vs-code-engineering vs-code-engineering Bot requested review from Copilot and pwang347 May 29, 2026 16:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@vs-code-engineering vs-code-engineering Bot marked this pull request as ready for review May 29, 2026 16:23
@vs-code-engineering vs-code-engineering Bot enabled auto-merge (squash) May 29, 2026 16:23
The Compile & Hygiene check failed due to a non-ASCII character (U+2014
em-dash) in a code comment. Replace with a standard hyphen.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Error] [GitHub.copilot-chat] unhandlederror-Response stream has been closed

2 participants