Skip to content

fix: normalize extension-provided CancellationToken in _findFilesBase (fixes #318999)#319018

Merged
vs-code-engineering[bot] merged 2 commits into
mainfrom
fix/cancellation-token-findfiles-318999-275eb4a93fd5c3e3
May 29, 2026
Merged

fix: normalize extension-provided CancellationToken in _findFilesBase (fixes #318999)#319018
vs-code-engineering[bot] merged 2 commits into
mainfrom
fix/cancellation-token-findfiles-318999-275eb4a93fd5c3e3

Conversation

@vs-code-engineering
Copy link
Copy Markdown
Contributor

Summary

Error: TypeError: i.onCancellationRequested is not a function in raceCancellationError when the SearchService.doSearch method passes an invalid token to raceCancellationError.

Root Cause: Extensions that bundle their own CancellationToken module (e.g., GitHub Copilot Chat) create tokens from a separate MutableToken class. These tokens fail the instanceof MutableToken check in the RPC protocol's isCancellationToken(). While they normally pass the duck-type fallback check, under certain bundling/runtime conditions the token is not recognized, causing it to be serialized over the wire as a plain object. Since functions and getters don't survive serialization, the main thread receives { _isCancelled: false, _emitter: null } — truthy but without onCancellationRequested.

Fixes #318999
Recommended reviewer: @roblourens

Culprit Commit

Most likely b02737df (May 14, 2026) by @osortega — "Add experimental opt-in to honor .gitignore in findFiles extension API (#316349)". This commit restructured _findFilesImpl and extracted _findFilesBase, creating the code path where extension-provided tokens are passed directly to the RPC proxy without validation.

Code Flow

sequenceDiagram
    participant Ext as Copilot Extension
    participant EH as ExtHostWorkspace
    participant RPC as RPC Protocol
    participant MT as MainThreadWorkspace
    participant SS as SearchService

    Ext->>EH: findFiles2(patterns, opts, bundledToken)
    EH->>EH: _findFilesImpl -> _findFilesBase(queryOptions, token)
    EH->>RPC: proxy.$startFileSearch(folder, options, bundledToken)
    Note over RPC: isCancellationToken(bundledToken) fails
    RPC->>RPC: Serializes token as plain object
    RPC->>MT: $startFileSearch(folder, options, brokenToken)
    MT->>SS: fileSearch(query, brokenToken)
    SS->>SS: doSearch -> raceCancellationError(promise, brokenToken)
    Note over SS: brokenToken.onCancellationRequested is undefined
    SS-->>SS: TypeError thrown
Loading

Affected Files

File Role
src/vs/workbench/api/common/extHostWorkspace.ts Producer — passes unvalidated token to RPC
src/vs/workbench/services/search/common/searchService.ts Consumer — calls raceCancellationError(promise, token)
src/vs/base/common/async.ts Crash site — token.onCancellationRequested()
src/vs/workbench/api/browser/mainThreadWorkspace.ts Intermediary — receives broken token from RPC

Repro Steps

  1. Use VS Code Insiders on Linux with Copilot Chat extension v0.50.0
  2. Trigger a file search operation via Copilot Chat (e.g., ask it to find files)
  3. The Copilot extension's bundled CancellationTokenSource creates a token
  4. Under certain conditions (likely bundler optimization or module duplication), the token fails isCancellationToken() in the RPC layer
  5. The serialized token arrives on the main thread without onCancellationRequested
  6. SearchService.doSearch crashes when calling raceCancellationError

How the Fix Works

Chosen approach (src/vs/workbench/api/common/extHostWorkspace.ts):

Added a validation guard in _findFilesBase that checks if the incoming token is recognized by CancellationToken.isCancellationToken() before passing it to the RPC proxy. If the token is not recognized (fails the instanceof and duck-type checks), a new CancellationTokenSource is created and linked to the original token's onCancellationRequested event. The linked token — which IS recognized by the RPC — is used instead. This fixes the problem at the data producer boundary (where the unrecognized token enters the RPC layer), not at the crash site.

Alternatives considered:

  • Adding a guard in mainThreadWorkspace.$startFileSearch to validate the received token — this would be fixing at the crash site rather than preventing bad data from being produced.
  • Modifying raceCancellationError to handle missing onCancellationRequested — this silences the error instead of fixing the cause.

Recommended Owner

@roblourens — owns the search/workspace extension API area where the fix is applied.

Generated by errors-fix · ● 219.4M ·

…fixes #318999)

Extensions that bundle their own CancellationToken module produce
tokens that fail the RPC protocol's instanceof check in
isCancellationToken(). When this happens, the token is serialized
over the wire as a plain object (without functions/getters), causing
'onCancellationRequested is not a function' on the main thread.

Fix by validating the token before passing it to the RPC proxy. If
it fails isCancellationToken(), create a linked CancellationTokenSource
with a properly recognized token.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 29, 2026 16:29
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.

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:31
@vs-code-engineering vs-code-engineering Bot enabled auto-merge (squash) May 29, 2026 16:31
@vs-code-engineering vs-code-engineering Bot merged commit ee1e7cc into main May 29, 2026
25 checks passed
@vs-code-engineering vs-code-engineering Bot deleted the fix/cancellation-token-findfiles-318999-275eb4a93fd5c3e3 branch May 29, 2026 17:51
@vs-code-engineering vs-code-engineering Bot added this to the 1.123.0 milestone May 29, 2026
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-i.onCancellationRequested is not a function

3 participants