[BUG] Windows: claude plugin eval fails with ENAMETOOLONG uv_spawn when the plugin dir holds ~3.5K chars of summed junction paths

Status Open
Reported on v2.1.278
Maintainer reply None cached
Activity 0 comments · opened Sep 22, 2026

What happens

On Windows, claude plugin eval <plugin-dir> fails every case with

ENAMETOOLONG: name too long, uv_spawn

before any child process starts, once the plugin directory contains enough NTFS junctions. With pnpm's default (isolated) layout, node_modules/ inside the plugin root holds hundreds of junctions into .pnpm, which is enough to trigger it. Every case then scores 0.

Environment

  • Claude Code 2.1.278 (also seen on 2.1.280), Windows 11 Pro 22631, Git Bash
  • Plugin root at a ~60-character path under C:\Users\<user>\...

What was measured

Three arms, same machine, same Claude Code version:

| arm | reparse points in plugin dir | result |
|---|---|---|
| the repository as it was (pnpm isolated node_modules) | 294 | FAIL (ENAMETOOLONG) |
| byte-identical robocopy /E /SL copy at a sibling path of the same length, junctions dereferenced | 0 | PASS |
| the same repository with node_modules moved aside, nothing else changed | 0 | PASS |

claude plugin eval <absolute path> run with cwd=C:\ still failed, so it depends on the plugin directory, not on the working directory or session state.

It is not MAX_PATH: a long-path enumeration (.NET, \\?\ prefix) found 23,509 files and none longer than 260 characters in either tree.

Threshold, by bisection with synthetic junctions

| each junction's own path length | last PASS (junction count) | first FAIL |
|---|---|---|
| ~90 chars | 36 | 37 |
| 199 chars | 17 | 18 |

Both flips land at roughly 3,400–3,600 characters of summed junction paths. The junctions' target length does not matter (151-char and 101-char targets both flipped at 37). The plugin root's own path length also shifts the budget.

On Windows, libuv returns UV_ENAMETOOLONG only when it translates ERROR_BUFFER_OVERFLOW or ERROR_FILENAME_EXCED_RANGE after CreateProcessW fails. That suggests something built from the directory listing (an environment block, a command line or a path list) grows past a limit. NODE_DEBUG=child_process printed nothing from the CLI, so I could not capture which field overflows.

Repro

  1. Create a minimal plugin with one eval case.
  2. Inside the plugin root, create ~40 directory junctions whose own paths are ~90 characters long (mklink /J ...).
  3. Run claude plugin eval <plugin-dir> --runs 1. Expected: the case runs. Actual: ENAMETOOLONG: name too long, uv_spawn.
  4. Remove the junctions and run again: it passes.

Workaround

node-linker=hoisted in .npmrc (pnpm's flat, npm-style layout: no junctions) makes the suite run. Plugins with a pnpm-managed node_modules in their root will hit this on Windows until eval stops walking or spawning with the junction set.

View original on GitHub ↗