Plugin install fails with EXDEV when home directory is on external drive

Resolved 💬 3 comments Opened Feb 6, 2026 by beomwookang Closed Feb 10, 2026

Bug Description

Plugin installation fails with EXDEV: cross-device link not permitted when the user's home directory (~) is on a different filesystem than the system temp directory (/var/folders/...).

Steps to Reproduce

  1. Set home directory to an external drive (e.g., /Volumes/ExternalSSD)
  2. Run /plugin marketplace add <marketplace-git-url>
  3. Run /plugin install <plugin-name>

Error Message

Error: Failed to install: EXDEV: cross-device link not permitted, rename
'/Volumes/ExternalSSD/.claude/plugins/cache/plugin-name' ->
'/var/folders/zg/.../T/claude-plugin-temp-1770392687628'

Root Cause

The plugin installer uses fs.rename() to move files between the plugin cache directory (~/.claude/plugins/cache/) and the system temp directory ($TMPDIR / /var/folders/...). On macOS, fs.rename() maps to the POSIX rename() syscall, which does not work across different filesystem mount points.

  • ~/.claude/plugins/cache/ → external SSD
  • $TMPDIR (/var/folders/...) → internal disk

This also affects marketplace registration — the marketplace clones successfully but fails to update known_marketplaces.json, resulting in a secondary error: Plugin "..." not found in any marketplace.

Expected Behavior

Plugin installation should work regardless of which filesystem the home directory resides on.

Suggested Fix

Replace fs.rename() with a cross-device safe alternative:

async function crossDeviceRename(src, dest) {
  try {
    await fs.rename(src, dest);
  } catch (err) {
    if (err.code === 'EXDEV') {
      await fs.cp(src, dest, { recursive: true });
      await fs.rm(src, { recursive: true });
    } else {
      throw err;
    }
  }
}

Environment

  • OS: macOS 15 (Darwin 25.2.0)
  • Home directory: External SSD (different mount point from internal disk)
  • TMPDIR: /var/folders/.../T/ (internal disk)
  • Claude Code: latest

View original on GitHub ↗

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