Skip to content

Windows: plugin update fails with "Access is denied (os error 5)" while VS Code is running (Copilot extension holds watcher handles on installed-plugins) #4095

Description

@FBakkensen

Describe the bug

copilot plugin update (and the same flow triggered from the GitHub Copilot desktop app) fails on Windows with:

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

The git fetch/checkout of the marketplace clone succeeds every time (the clone under %LOCALAPPDATA%\copilot\marketplaces\... ends up at the target commit, working tree clean). The failure happens in the final step that replaces ~\.copilot\installed-plugins\<marketplace>\<plugin>.

Root cause (verified with a system-wide handle enumeration via NtQuerySystemInformation(SystemExtendedHandleInformation)): VS Code's Copilot extension holds directory watcher handles (access mask 0x100081, i.e. ReadDirectoryChangesW-style) on the installed plugin folder itself and its hooks, agents, and skills subdirectories:

pid=15064 handle=0x424 access=0x100081 path=\?\C:\Users\<user>\.copilot\installed-plugins\<marketplace>\al-agentic-dev
pid=15064 handle=0x65c access=0x100081 path=...\al-agentic-dev\hooks
pid=15064 handle=0x678 access=0x100081 path=...\al-agentic-dev\agents
pid=15064 handle=0x67c access=0x100081 path=...\al-agentic-dev\skills

(pid 15064 = Code.exe --type=utility --utility-sub-type=node.mojom.NodeService — the VS Code file-watcher host.)

On Windows, a directory that has an open watcher handle cannot be renamed/replaced, so the installer's folder swap fails with ERROR_ACCESS_DENIED (5). Closing VS Code releases the handles and the identical update command then succeeds immediately (v2.5.0 → v3.0.0 in my case).

This is very confusing for users: restarting the Copilot desktop app doesn't help, and even a reboot doesn't help if VS Code relaunches before the update is retried. The error message gives no hint that another application is holding the folder.

Affected version

GitHub Copilot CLI 1.0.70 (also reproduced through GitHub Copilot desktop app 1.0.21, which calls the same installer via plugins.update)

Steps to reproduce the behavior

  1. On Windows, install a plugin from a marketplace, with the VS Code GitHub Copilot extension active (so it watches ~\.copilot\installed-plugins\...).
  2. With VS Code still running, run copilot plugin update <plugin>@<marketplace> (or click Update in the desktop app's plugin settings).
  3. Error: Failed to install plugin: Error: Access is denied. (os error 5). The installed plugin stays at the old version.
  4. Close VS Code, run the same command → update succeeds.

Expected behavior

The update should succeed while VS Code is running — e.g. by copying the new version into place file-by-file instead of renaming/removing the directory root, by retrying with backoff, or by staging to a sibling dir and swapping with FILE_RENAME_FLAG_POSIX_SEMANTICS. Failing that, the error message should name the process holding the directory (the Restart Manager API can identify it) so users don't reach for a reboot.

Additional context

  • Operating system: Windows 11 Pro 10.0.26200, x86_64
  • Diagnosis details: per-file probes all pass (no file locks, no read-only attributes, ACLs fine — Restart Manager reports nothing because it doesn't surface directory watcher handles); only the rename of the plugin folder root fails. Bisected by rename-probing every subdirectory: only the root and the three watched subdirs are held.
  • The plugin in question ships hooks/, agents/, skills/ and an extensions/ canvas extension, but the bug is independent of plugin content — any plugin folder watched by VS Code's Copilot extension will hit it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions