npm / npm/cli

[BUG] ERESOLVE on in-place update: conflict from an optional peer that never gets installed

Open
#9,807 0 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug Needs Triage
Dominant language
JavaScript
Stars
10.1k
Forks
4.7k
Avg merge
2d 2h
Merged PRs (30d)
19

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
This is not just a request to bump a dependency for a CVE
  • This is not solely a request to bump a dependency for a CVE
Current Behavior

Bumping one dev dependency by a single patch version fails with ERESOLVE. The conflict npm reports comes from a package it never installs.

Going from @vitejs/plugin-react@6.0.3 to 6.0.4 against an existing lockfile:

npm error code ERESOLVE
npm error ERESOLVE could not resolve
npm error
npm error While resolving: eresolve-repro@1.0.0
npm error Found: @vitejs/plugin-react@6.0.3
npm error node_modules/@vitejs/plugin-react
npm error   dev @vitejs/plugin-react@"6.0.4" from the root project
npm error
npm error Could not resolve dependency:
npm error dev @vitejs/plugin-react@"6.0.4" from the root project
npm error
npm error Conflicting peer dependency: @babel/core@8.0.1
npm error node_modules/@babel/core
npm error   peer @babel/core@"^8.0.0" from @babel/plugin-transform-runtime@8.0.1
npm error   node_modules/@babel/plugin-transform-runtime
npm error     peerOptional @babel/plugin-transform-runtime@"^7.29.0 || ^8.0.0-rc.1" from @rolldown/plugin-babel@0.2.3
npm error     node_modules/@rolldown/plugin-babel
npm error       peerOptional @rolldown/plugin-babel@"^0.1.7 || ^0.2.0" from @vitejs/plugin-react@6.0.4
npm error       node_modules/@vitejs/plugin-react
npm error         dev @vitejs/plugin-react@"6.0.4" from the root project

It gets there through two levels of optional peers:

@vitejs/plugin-react -> peerOptional @rolldown/plugin-babel -> peerOptional @babel/plugin-transform-runtime -> peer @babel/core@^8

and that last one collides with the @babel/core@7.29.7 already in the tree.

@rolldown/plugin-babel is not in the lockfile before the update, and it's not there after a clean install of the updated package.json either. npm is right not to install it. It still fails the install over a conflict that only that package would have caused.

I think this is the same bug as #8416, just a smaller case. The repros on that thread all involve real version conflicts between packages that do get installed. Here nothing conflicting ends up in the tree in any working state.

Expected Behavior

Step 2 below should resolve. Step 3 shows the end state is fine: same package.json, no lockfile, installs without complaint, no @rolldown/plugin-babel anywhere, @babel/core still 7.29.7.

An optional peer that can't be satisfied should get skipped, the way it already is on a clean install.

Steps To Reproduce
  1. In an empty directory, create this package.json:

    {
      "name": "eresolve-repro",
      "version": "1.0.0",
      "devDependencies": {
        "@vitejs/plugin-react": "6.0.3",
        "workbox-build": "7.3.0"
      }
    }
    
  2. Install the baseline. Works:

    npm install
    
  3. Bump the one dev dependency and reinstall. Fails with ERESOLVE:

    npm pkg set devDependencies.@vitejs/plugin-react=6.0.4
    npm install
    
  4. Drop the lockfile and install the same package.json. Works:

    rm -rf package-lock.json node_modules
    npm install
    
  5. Check that the package from the error message isn't actually there:

    npm ls @rolldown/plugin-babel   # └── (empty)
    npm ls @babel/core              # only 7.29.7, under workbox-build
    

Some other things I checked:

  • Same result on npm 10.9.4, 11.16.0 and 12.0.1.
  • vite-plugin-pwa@1.3.0 works in place of workbox-build@7.3.0 (it depends on workbox-build). That's how I ran into this, on a Vite PWA app whose automated dependency PR broke.
  • workbox-build doesn't reduce any further. @babel/core@7.29.7 on its own doesn't trigger it, and neither does adding @babel/preset-env or @rollup/plugin-babel, so it looks like it needs the whole Babel 7 tree workbox-build pulls in.
  • Nothing changed in the package being bumped. @vitejs/plugin-react 6.0.3 and 6.0.4 declare identical peerDependencies and peerDependenciesMeta. What changed upstream is @babel/plugin-transform-runtime@8.0.1, published 2026-06-17, landing inside the existing ^7.29.0 || ^8.0.0-rc.1 range.

Impact: this breaks update bots. Renovate reports Artifact file update failure and opens the PR with package.json bumped but the lockfile untouched, so CI then dies at npm ci on the mismatch. Fixing it by hand means regenerating the whole lockfile, which drags in unrelated transitive bumps the bot never meant to make.

Workarounds:

  • delete package-lock.json and reinstall
  • --legacy-peer-deps
  • "overrides": { "@babel/plugin-transform-runtime": "^7.29.0" }

Possibly related:

  • #8416, same bug as far as I can tell, with larger repros
  • #9324, same "clean install works, in-place update doesn't" symptom, but that one is about genuine conflicts between packages that do get installed
Environment
  • npm: 11.16.0
  • Node.js: 24.18.0
  • OS Name: macOS 15.7.7
  • System Model Name: Macbook Pro
  • npm config:
; "user" config from /Users/user/.npmrc

//npm.pkg.github.com/:_authToken = (protected)

; node bin location = /Users/user/.nvm/versions/node/v24.18.0/bin/node
; node version = v24.18.0
; npm local prefix = /private/tmp
; npm version = 11.16.0
; cwd = /private/tmp
; HOME = /Users/user
; Run `npm config ls -l` to show all defaults.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the issue with the package.json and npm install commands in the report, comparing the in-place update with the clean install after removing package-lock.json and node_modules. Trace how the resolver handles the two levels of optional peers and the existing @babel/core@7.29.7. Done means the update resolves without installing @rolldown/plugin-babel or reporting a conflict, while the clean-install result remains unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
cli, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.