Repository navigation
Description
Verify latest release
- I verified that the issue exists in the latest pnpm release
pnpm version
No response
Which area(s) of pnpm are affected? (leave empty if unsure)
Dependencies resolver, Lockfile
Link to the code that reproduces this issue or a replay of the bug
No response
Reproduction steps
Verified with pnpm 12.8.2 (Node.js 22.23.1, macOS).
{
"name": "pnpm-stale-optional-peer",
"private": true,
"dependencies": { "vue": "3.5.40" },
"devDependencies": { "@vue/test-utils": "2.5.1" }
}@vue/test-utils@2.5.1 declares @vue/compiler-dom, @vue/server-renderer and vue as peers (3.x), with @vue/server-renderer marked optional. vue@3.5.x depends on @vue/server-renderer at its own exact version.
$ pnpm install –lockfile-only
$ grep "^ '@vue/test-utils@2.5.1(" pnpm-lock.yaml
'@vue/test-utils@2.5.1(@vue/compiler-dom@3.5.40)(@vue/server-renderer@3.5.40)(vue@3.5.40)':
# bump vue to 3.5.43 in package.json
$ pnpm install –lockfile-only
$ pnpm dedupe –lockfile-only
$ grep -E "^ '@vue/(test-utils@2.5.1\(|server-renderer@)" pnpm-lock.yaml
'@vue/server-renderer@3.5.40':
'@vue/server-renderer@3.5.43':
'@vue/test-utils@2.5.1(@vue/compiler-dom@3.5.43)(@vue/server-renderer@3.5.40)(vue@3.5.43)':Controls, run from the same stale lockfile:
- A fresh resolve (
rm pnpm-lock.yaml && pnpm install) gives(@vue/server-renderer@3.5.43), a single copy. pnpm update @vue/server-rendereralso moves it to 3.5.43, thanks to fix(deps-resolver): update auto-installed peers thatpnpm update <name>targets #15632
Describe the Bug
After vue goes from 3.5.40 to 3.5.43, the required peer @vue/compiler-dom follows it to 3.5.43. The optional peer @vue/server-renderer stays on 3.5.40, and neither pnpm install nor pnpm dedupe moves it. The lockfile keeps @vue/server-renderer@3.5.40 together with its whole 3.5.40 dependency tree (runtime-dom, runtime-core, reactivity, shared), next to the 3.5.43 copies vue brings in. That happens even though 3.5.43 is already in the graph and satisfies the 3.x peer range.
This caused a real failure for us, not just a bigger lockfile. @vue/test-utils got into a Vite dev build and brought the second Vue runtime with it. Both runtimes register the global __VUE_HMR_RUNTIME__, the stale one registered last, and hot module replacement for Vue components silently stopped working. Nothing hinted at a version mismatch.
This looks like #11800 (fixed in 12.7.0 by #15629), but that fix doesn't cover this case:
- this is a single project, not a workspace;
- the stale peer is not recorded under
importers:, only inside@vue/test-utils' own peer suffix; - no project specifier names
@vue/server-renderer. The newer version comes from another package's regular dependency (vue→@vue/server-renderer@3.5.43).
Expected Behavior
When a version that is already in the graph satisfies an optional peer's range, pnpm install (or at least pnpm dedupe) should resolve the peer to it. That's what a fresh install does, and what already happens here for the required peer @vue/compiler-dom.
Which Node.js version are you using?
22.23.1
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)
No response
Contributing a fix
- I am working on a fix
Activity
altaywtf commentedon Sep 30, 2026
I'm working on a fix for this.
Written by an agent (Claude Code, claude-opus-5-5).
altaywtf commentedon Sep 30, 2026
A fix is ready for review in #16445. CI is green.
Written by an agent (Claude Code, claude-opus-5-5).
fix(deps-resolver): drop a stale locked optional-peer version (#16445)
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