microsoft / microsoft/vscode

Windows: CLI plugin discovery watchers block plugin install, update, and uninstall

Open
#334,391 0 comments 0 reactions 1 assignee Claimed by @pwang347 View on GitHub
agent-plugins bug chat windows
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

## Type of issue

Bug in VS Code's discovery of plugins installed by the GitHub Copilot CLI.

Upstream report: https://github.com/github/copilot-cli/issues/4095
Related duplicate: https://github.com/github/copilot-cli/issues/4151
Introducing VS Code change: https://github.com/microsoft/vscode/pull/314805

## Problem

On Windows, GitHub Copilot CLI plugin install, update, and uninstall can fail with:

```text
Failed to install plugin: Error: Access is denied. (os error 5)
```

The upstream investigation enumerated open handles and found VS Code's file-watcher utility holding `ReadDirectoryChangesW`-style handles on the CLI-installed plugin root and component directories such as `hooks`, `agents`, and `skills`. Closing all VS Code windows releases the handles and the same CLI operation succeeds immediately.

## VS Code causal chain

`CopilotCliAgentPluginDiscovery` scans:

```text
~/.copilot/installed-plugins///
```

It watches each marketplace directory and treats every immediate child directory as a plugin source, including CLI staging directories named like:

```text
..tmp--0
```

The shared `AbstractAgentPluginDiscovery` then creates non-recursive watchers on:

- the plugin root
- `commands`
- `skills`
- `agents`
- `hooks`
- other resolved component paths

Relevant code:

- CLI discovery and marketplace bucket watchers: `src/vs/workbench/contrib/chat/common/plugins/agentPluginServiceImpl.ts`
- Plugin root and component watchers: `AbstractAgentPluginDiscovery._toPlugin` in the same file
- Windows watcher backend: `src/vs/platform/files/node/watcher/parcel/parcelWatcher.ts`

This causes two related failure modes:

1. **Fresh installs can fail intermittently.** For sufficiently large plugins, VS Code discovers the staging directory and opens watcher handles before the CLI performs its final rename. Small plugins can finish the rename before discovery reacts, making the bug appear size- or plugin-dependent.
2. **Updates and uninstalls can fail consistently.** VS Code already has persistent watcher handles inside the final installed directory. The CLI cannot atomically rename/replace that directory on Windows, and VS Code cannot observe the successful parent-directory change that would cause it to rebuild or dispose those watchers.

The handle paths reported upstream match the watchers created by `AbstractAgentPluginDiscovery` exactly.

## Steps to reproduce

1. On Windows, install a Copilot CLI plugin under `~/.copilot/installed-plugins/...`.
2. Open VS Code with Copilot/plugin discovery active and confirm the plugin is discovered.
3. While VS Code remains open, run:

```text
copilot plugin update @
```

The same problem can affect `plugin install` and `plugin uninstall`.
4. Observe `Access is denied. (os error 5)` during the final directory rename/replacement.
5. Close VS Code and repeat the operation; it succeeds.

## Expected behavior

VS Code should allow the CLI to atomically install, replace, or remove CLI-owned plugin directories while still reflecting changes without requiring a reload.

## Suggested direction

Avoid placing persistent watcher handles inside CLI-owned plugin directories. For example:

- watch the installed-plugins root or marketplace buckets from an ancestor, preferably recursively;
- use ancestor events to invalidate and rediscover affected plugins;
- do not create plugin-root/component watchers for `CopilotCliAgentPluginDiscovery` sources;
- exclude CLI staging/tombstone directory names from discovery.

Filtering temporary directory names alone would reduce intermittent fresh-install failures but would not fix update/uninstall, because watchers on the existing final plugin directory would remain.

## Validation needed

Add Windows coverage, or a focused watcher test where possible, proving that a discovered CLI plugin directory can be renamed/replaced while VS Code is running. Also cover staging directories so they are not surfaced as installed plugins.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.