claude-code - 💡(How to fix) Fix plugin install fails on Windows with EBUSY when other sessions hold cache handles [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#51840Fetched 2026-04-23 07:43:32
View on GitHub
Comments
0
Participants
1
Timeline
4
Reactions
0
Author
Participants
Timeline (top)
labeled ×4

claude plugin install <plugin>@<source> fails reproducibly on Windows when any other Claude Code session is currently running a plugin loaded from ~/.claude/plugins/cache/<source>/<name>/<version>/:

× Failed to install plugin "choir@choir":
  EBUSY: resource busy or locked, rm 'C:\Users\svere\.claude\plugins\cache\choir'

Error Message

  • Disk full during staging: clean up staging, abort with clear error

Root Cause

Root cause (best reading)

Code Example

× Failed to install plugin "choir@choir":
  EBUSY: resource busy or locked, rm 'C:\Users\svere\.claude\plugins\cache\choir'
RAW_BUFFERClick to expand / collapse

Summary

claude plugin install <plugin>@<source> fails reproducibly on Windows when any other Claude Code session is currently running a plugin loaded from ~/.claude/plugins/cache/<source>/<name>/<version>/:

× Failed to install plugin "choir@choir":
  EBUSY: resource busy or locked, rm 'C:\Users\svere\.claude\plugins\cache\choir'

Root cause (best reading)

The installer unconditionally rm -rfs ~/.claude/plugins/cache/<source>/ before writing the new version. On Windows, file handles are exclusive — so if even one running session has anything loaded from that directory (e.g. a bun server.ts as a peer MCP), the rm fails and the upgrade aborts.

We verified this during a 0.4.5 → 0.5.0 rollout with 12 concurrent bun.exe processes across 7 Claude Code sessions — the upgrade didn't succeed until sessions naturally cycled off the old version.

Impact

Especially painful for multi-session plugins: the users most likely to have the plugin installed are also the ones most likely to have other sessions holding handles to the cache. The failure is silent about which session is holding a handle, so the only remediation is "close everything and retry."

Proposed shape (stage + swap)

  1. Download new version to cache/<source>/<name>/<version>.staging.<pid>/
  2. Validate (manifest, plugin.json, minimum file set)
  3. Atomically rename …staging.<pid>/…<version>/ (rename on Windows is atomic when src+dst share a volume)
  4. Update version pointer (cache/<source>/plugin.json or equivalent) with a temp-file + rename
  5. Opportunistically GC old versions: walk existing version dirs, attempt rm -rf, on EBUSY leave a .stale-<version> marker and skip
  6. Next install sweeps the marker files once handles have released

New sessions get the new version immediately; existing sessions keep running on the old version until they restart — no disruption, no EBUSY.

Edge cases worth handling

  • Same-version reinstall: hash-compare, delete staging if identical, exit 0
  • Disk full during staging: clean up staging, abort with clear error
  • Interrupted staging: on next install, scan for *.staging.<dead-pid> dirs and prune
  • Concurrent installs: sentinel file cache/<source>/.install.lock.<pid>; wait N seconds, abort if still held

Repro (Windows)

  1. Install any plugin that loads long-running processes from the cache (we see it with choir, but the shape should generalize)
  2. Open 2+ Claude Code sessions that exercise it
  3. In a third session, run claude plugin install <plugin>@<source> targeting an upgrade — EBUSY

Cross-link

Downstream tracking: mercurai/choir#631

extent analysis

TL;DR

Implement a staging-based installation process to avoid file handle conflicts on Windows.

Guidance

  • Modify the claude plugin install command to use a staging directory for new versions, as outlined in the proposed shape (stage + swap) section.
  • Implement atomic rename operations to minimize the risk of file handle conflicts.
  • Handle edge cases such as same-version reinstall, disk full during staging, interrupted staging, and concurrent installs.
  • Use a sentinel file to prevent concurrent installs from interfering with each other.

Example

No code snippet is provided as the issue does not contain specific code that needs to be modified. However, the proposed shape (stage + swap) section provides a clear outline of the steps required to implement the staging-based installation process.

Notes

The proposed solution assumes that the claude plugin install command has the ability to download and validate new versions of plugins, as well as update version pointers and perform garbage collection of old versions. Additionally, the solution relies on the atomicity of rename operations on Windows when the source and destination share a volume.

Recommendation

Apply the proposed staging-based installation process workaround to avoid file handle conflicts on Windows. This approach allows for seamless upgrades without disrupting existing sessions and provides a clear solution to the EBUSY error.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING