Repository navigation
Description
Is there an existing issue for this?
- I have searched the existing issues
This issue exists in the latest npm version
- I am using the latest npm
Current Behavior
npm update can successfully write a package-lock.json that a subsequent plain npm install immediately rejects with ERESOLVE.
The concrete repro uses Storybook and Vite+:
- valid starting lockfile:
[email protected],@storybook/[email protected],[email protected] [email protected]has novite-pluspeer dependency; its only peer dependency is optionalprettiernpm updateexits0and updates the lockfile to[email protected],@storybook/[email protected],[email protected][email protected]has optional peervite-plus@^0.1.15- semver
^0.1.15does not include any0.2.xrelease, so neither[email protected]nor[email protected]can satisfy it - the next
npm installfails withERESOLVE
So npm starts from a valid/installable lockfile, npm update reports success, but npm's own install command cannot reproduce the updated lockfile.
Expected Behavior
npm update should not leave the project with a lockfile that npm install immediately rejects.
Reasonable outcomes would be either:
npm updateavoids selecting updates that create an install-invalid peer graph, ornpm updatefails non-zero and does not leave the lockfile in the invalid updated state.
Steps To Reproduce
This uses npx --yes [email protected] ... only to force the latest npm version even on machines with an older npm on PATH. The initial install intentionally pins exact versions while saving caret ranges, creating a valid starting lockfile that a later update corrupts.
rm -rf /tmp/npm-update-install-eresolve-repro
mkdir -p /tmp/npm-update-install-eresolve-repro
cd /tmp/npm-update-install-eresolve-repro
npx --yes [email protected] init -y
npx --yes [email protected] install --save-dev --save-prefix='^' \
[email protected] \
@storybook/[email protected] \
[email protected] \
[email protected] \
[email protected]
node - <<'NODE'
const p = require('./package-lock.json').packages
console.log('initial lock:', {
storybook: p['node_modules/storybook'].version,
storybookPeers: p['node_modules/storybook'].peerDependencies,
storybookPeerMeta: p['node_modules/storybook'].peerDependenciesMeta,
reactVite: p['node_modules/@storybook/react-vite'].version,
vitePlus: p['node_modules/vite-plus'].version,
})
NODE
echo '--- npm update ---'
npx --yes [email protected] update
echo '--- lockfile after update ---'
node - <<'NODE'
const p = require('./package-lock.json').packages
console.log('after update lock:', {
storybook: p['node_modules/storybook'].version,
storybookPeers: p['node_modules/storybook'].peerDependencies,
storybookPeerMeta: p['node_modules/storybook'].peerDependenciesMeta,
reactVite: p['node_modules/@storybook/react-vite'].version,
vitePlus: p['node_modules/vite-plus'].version,
})
NODE
echo '--- npm install after update ---'
npx --yes [email protected] installObserved output from the important parts:
initial lock: {
storybook: '10.3.5',
storybookPeers: { prettier: '^2 || ^3' },
storybookPeerMeta: { prettier: { optional: true } },
reactVite: '10.3.5',
vitePlus: '0.2.0'
}
added 5 packages, changed 12 packages, and audited 227 packages in 3s
after update lock: {
storybook: '10.4.6',
storybookPeers: {
'@types/react': '^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0',
prettier: '^2 || ^3',
'vite-plus': '^0.1.15'
},
storybookPeerMeta: {
'@types/react': { optional: true },
prettier: { optional: true },
'vite-plus': { optional: true }
},
reactVite: '10.4.6',
vitePlus: '0.2.1'
}
npm error code ERESOLVE
npm error ERESOLVE could not resolve
npm error
npm error While resolving: [email protected]
npm error Found: [email protected]
npm error node_modules/vite-plus
npm error dev vite-plus@"^0.2.0" from the root project
npm error
npm error Could not resolve dependency:
npm error peerOptional vite-plus@"^0.1.15" from [email protected]
Environment
npm = 11.17.0
node = v24.17.0
os = macOS arm64
package manager = npm / package-lock.json
Activity
fix(arborist): validate peerOptional conflicts in no-save mutations (n…