npm ERESOLVE "unable to resolve dependency tree" in CI - Fix It Properly
ERESOLVE means npm could not build a dependency tree that satisfies every package and its declared peers. The durable fix is reconciling the versions, not forcing past the check.
What this error means
npm install or npm ci stops before installing anything and prints ERESOLVE with the conflicting package and the peer it could not satisfy. The same conflict reproduces on every clean run.
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: my-app@1.0.0
npm ERR! Found: react@17.0.2
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^18.0.0" from @acme/ui@4.2.0Diagnose it: reproduce the CI install locally
Install failures are usually environment drift rather than a broken lockfile: a different package-manager major, a different Node version, or a cache that is being restored from a run with different inputs. Reproduce the CI conditions before changing the lockfile, because regenerating it hides the real cause.
# match the runner exactly, then install from a clean slate
node --version && npm --version
rm -rf node_modules
npm ci --foreground-scripts
# if that succeeds locally but fails in CI, the difference is the cache
# or the package-manager version, not your lockfileCommon causes
A package requires a peer version you do not have installed
A dependency declares a peer (for example react@^18) that conflicts with the version pinned in your project, so npm cannot pick a single satisfying version.
A stale or partially edited lockfile
An out-of-date package-lock.json can encode a tree that no longer reconciles against the current package.json ranges.
How to fix it
Resolve the actual version conflict
- Read the ERESOLVE output to see which peer is required versus what is installed.
- Upgrade or downgrade one side so the major versions are compatible.
- Regenerate the lockfile with rm package-lock.json && npm install, then commit it.
Temporary unblock with legacy peer deps
- Only if you must ship now and accept the risk, install ignoring peer conflicts.
- Track the conflict and fix the version mismatch afterward.
npm ci --legacy-peer-depsVerify the fix survives a cold cache
A green run immediately after a fix often proves nothing, because it restored a cache written before the change. Force a cold install once to confirm the fix is real.
# temporarily bust the cache key to prove the fix on a cold runner
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: package-lock.json
# then bump this suffix once, run, and remove it
# key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}-v2How to prevent it
- Keep dependencies and their peers on compatible majors, commit the lockfile, and let renovate or dependabot upgrade peer-linked packages together so the tree always resolves.