Repository navigation
Description
Verify latest release
- I verified that the issue exists in the latest pnpm release
pnpm version
12.7.0 to 12.8.2 and current main. Last good: 12.6.0.
Which area(s) of pnpm are affected? (leave empty if unsure)
CLI
Link to the code that reproduces this issue or a replay of the bug
No response
Reproduction steps
A workspace of 500 projects, each with 20 workspace:* dependencies (no registry needed):
mkdir ws && cd ws
printf 'packages:\n - "packages/*"\n' > pnpm-workspace.yaml
echo '{"name":"root","private":true}' > package.json
N=500 K=20
for ((i = 0; i < N; i++)); do
mkdir -p packages/p$i; deps=""
for ((j = 1; j <= K; j++)); do deps+="\"p$(( (i + j) % N ))\":\"workspace:*\","; done
printf '{"name":"p%d","version":"1.0.0","dependencies":{%s}}\n' $i "${deps%,}" > packages/p$i/package.json
done
pnpm install --offline
hyperfine -N -w 5 -r 40 'pnpm install --offline --reporter=silent'
/usr/bin/time -l pnpm install --offline --reporter=silent # macOS: instructions retiredDescribe the Bug
The repeat pnpm install that prints "Already up to date" now costs one symlink-following stat per direct dependency of every workspace project, run one after another on the main thread. The cost grows with the total number of direct dependency entries, not with what changed.
macOS arm64, 18 cores, the workspace above:
| pnpm | wall (hyperfine, 40 runs) | instructions retired |
|---|---|---|
| 12.6.0 | 18.2 ms ± 0.5 | 337-339M |
| 12.8.2 | 39.5 ms ± 1.6 | 636-639M |
On Linux x64 (strace -f -c, 12.8.2 vs 12.6.0) the stat-family syscall count goes from 1561 to 11554 at 10000 entries, and from 1561 to 2554 at 1000: exactly one more per entry.
The check was added in #15569 (12.7.0 and 11.28.0; 12.7.0 shows the same jump over 12.6.0): direct_dependency_link_dangling in optimistic_repeat_install/modules_dirs.rs, called as the last gate of the fast path. #16478 changes which dependencies that function probes, not how.
pnpm 11 has the same probe (findDanglingDirectDependencyLink), but it already runs the stat calls concurrently through Promise.all.
Expected Behavior
A no-op install stays close to 12.6.0, while still relinking a direct dependency whose link points to a missing target.
Which Node.js version are you using?
26.10.0
Which operating systems have you used?
- macOS
- Windows
- Linux
If your OS is a Linux based, which one it is? (Include the version if relevant)
Ubuntu (Cloudflare container)
Contributing a fix
- I am working on a fix
Written by an agent (Claude Code, Opus 5.5).
Activity
altaywtf commentedon Oct 1, 2026
I'm working on a fix for this.
Written by an agent (Claude Code, Opus 5.5).
altaywtf commentedon Oct 1, 2026
A fix is ready for review in #16488. CI is green.
Written by an agent (Claude Code, Opus 5.5).
perf(install): probe direct dependency links in parallel on repeat in…
fix(deps): update dependencias no-major (#23)
chore(deps): update pnpm to v12.9.0
chore(deps): update pnpm to v12.9.0
chore(deps): update pnpm to v12.9.0
chore(deps): update pnpm to v12.9.0
chore(deps): update pnpm to v12.9.0