claude plugin marketplace add fails with EPERM rename on Windows (clone-then-rename race with Defender / Indexer)

Resolved 💬 3 comments Opened May 12, 2026 by ourladypeace2011-commits Closed May 15, 2026

Symptom

claude plugin marketplace add <owner>/<repo>@<branch> fails on Windows with:

✘ Failed to add marketplace: Failed to finalize marketplace cache.
Please manually delete the directory at
C:\Users\user\.claude\plugins\marketplaces\<slug> if it exists and try again.

Technical details: EPERM: operation not permitted, rename
'C:\Users\user\.claude\plugins\marketplaces\<owner>-<repo>'
-> 'C:\Users\user\.claude\plugins\marketplaces\<slug>'

Root cause (suspected)

CC's add-from-GitHub flow appears to be:

  1. git clone to <owner>-<repo>/ (intermediate name)
  2. rename to <slug> (marketplace's declared name)

On Windows, immediately after git clone finishes, file handles are still held by Windows Defender (real-time scan of newly-written files) and/or Windows Search Indexer for ~1-3 seconds. The synchronous rename in step 2 hits this lock window and fails with EPERM.

Reproduction

Consistent on Windows 11 + Claude Code 2.1.139 + Node v24.12.0. Tested case: zz41354899/SwiftMographer@main. Both retries and pre-creating the destination directory fail (CC cleans up source + dest on each failure, so retry has nothing to recover from).

Workaround (verified working)

claude plugin marketplace add accepts a local path as <source> (per --help), bypassing the clone+rename two-step:

mkdir -p C:/Users/user/.local-marketplaces
git clone --depth 1 --branch main https://github.com/<owner>/<repo>.git \
  C:/Users/user/.local-marketplaces/<slug>
claude plugin marketplace add C:/Users/user/.local-marketplaces/<slug>

This works first try. Drawback: the local source doesn't track the upstream — user must git pull + claude plugin marketplace update <slug> manually.

Suggested fixes (in order of preference)

  1. Retry the rename with backoff (e.g., 100ms → 500ms → 2s, max 3 attempts). Defender lock typically releases within 1-2 seconds.
  2. Clone directly into the final slug name instead of clone-then-rename. This requires reading the marketplace's name field via shallow fetch or pre-clone introspection, but eliminates the rename step entirely.
  3. Detect EPERM specifically and surface the local-path workaround in the error message (current message says "manually delete" which doesn't help — both source and dest are gone after auto-cleanup).

Mac / Linux note

POSIX rename doesn't fail on open file descriptors, so this only manifests on Windows. macOS / WSL users won't hit it.

Environment

  • Claude Code 2.1.139
  • Windows 11 Pro 10.0.26200
  • Node v24.12.0
  • Git 2.x (Git for Windows)

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗