npm ERESOLVE unable to resolve dependency tree (tested)

ERESOLVE unable to resolve dependency tree is npm's install-time error for a peer dependency conflict: two packages in your tree want incompatible versions of the same dependency. We built a real conflict (react-dom@16 wanting react@16, next to react@19 in the same project), ran a plain install, then measured what --legacy-peer-deps, --force, and the overrides field each actually do.

1. What ERESOLVE means

Since npm 7, npm install checks peer dependencies strictly. If package A requires react@^16 as a peer and your project (or another dependency) installs react@19, npm cannot build one dependency tree that satisfies both. It stops and prints ERESOLVE unable to resolve dependency tree instead of guessing. Per npm's own docs, npm 6 and earlier only warned about this and installed anyway; we did not have npm 6 on this box to confirm that directly.

This is the generic form of a family of peer-dependency conflicts: the same error appears for Angular, ESLint plugins, Babel presets, or any package tree with peer version ranges that don't overlap.

2. Our test setup

We created a throwaway project with two real npm packages whose peer requirements genuinely conflict:

{
  "dependencies": {
    "react": "19.3.0",
    "react-dom": "16.14.0"
  }
}

react-dom@16.14.0 declares "peerDependencies": { "react": "^16.14.0" }. We asked for react@19.3.0 directly. Those ranges don't overlap, so this is a genuine conflict, not a contrived one.

3. The exact error

Running npm install with nothing else in the project printed this and exited non-zero:

npm error code ERESOLVE
npm error ERESOLVE unable to resolve dependency tree
npm error
npm error While resolving: eresolve-repro@1.0.0
npm error Found: react@19.3.0
npm error node_modules/react
npm error   react@"19.3.0" from the root project
npm error
npm error Could not resolve dependency:
npm error peer react@"^16.14.0" from react-dom@16.14.0
npm error node_modules/react-dom
npm error   react-dom@"16.14.0" from the root project
npm error
npm error Fix the upstream dependency conflict, or retry this command with --force or --legacy-peer-deps to accept an incorrect (and potentially broken) dependency resolution.

No node_modules was created at all. Running npm ls at that point reports both packages as unmet, read straight from package.json:

eresolve-repro@1.0.0 /tmp/npm-eresolve-guide
├── UNMET DEPENDENCY react-dom@16.14.0
└── UNMET DEPENDENCY react@19.3.0

4. Does --legacy-peer-deps work?

Yes, and silently. npm install --legacy-peer-deps printed no warning at all:

added 8 packages, and audited 9 packages in 974ms
found 0 vulnerabilities

Afterward npm ls showed a normal-looking tree:

eresolve-repro@1.0.0
├── react-dom@16.14.0
└── react@19.3.0

This flag makes npm skip peer dependency checks the way npm 6 did. It does not change which versions get installed here; it only stops npm from refusing. It does not check compatibility at all, so a silent install is not proof the combination works at runtime.

5. Does --force work, and how is it different?

Also yes, but noisily. npm install --force printed the conflict as a warning instead of an error, then installed anyway:

npm warn using --force Recommended protections disabled.
npm warn ERESOLVE overriding peer dependency
npm warn While resolving: react-dom@16.14.0
npm warn Found: react@19.3.0
npm warn node_modules/react
npm warn   react@"19.3.0" from the root project
npm warn
npm warn Could not resolve dependency:
npm warn peer react@"^16.14.0" from react-dom@16.14.0
npm warn node_modules/react-dom
npm warn   react-dom@"16.14.0" from the root project
npm warn
npm warn Conflicting peer dependency: react@16.14.0

added 8 packages, and audited 9 packages in 866ms
found 0 vulnerabilities

The resulting npm ls tree was identical to the --legacy-peer-deps case in this project: react@19.3.0 and react-dom@16.14.0, nothing nested or duplicated. The practical difference we measured is visibility: --force tells you exactly which peer conflict it overrode; --legacy-peer-deps says nothing. --force also re-downloads and re-verifies packages it would otherwise skip, so on a populated cache it can be slower; on this conflict with an empty cache both took under a second longer either way.

6. The modern fix: overrides

npm's overrides field in package.json lets you pin what version a nested or peer dependency resolves to, project-wide. We added this and nothing else:

{
  "dependencies": {
    "react": "19.3.0",
    "react-dom": "16.14.0"
  },
  "overrides": {
    "react-dom": {
      "react": "19.3.0"
    }
  }
}

With that in place, a plain npm install (no flags) succeeded with no warning at all:

added 8 packages, and audited 9 packages in 714ms
found 0 vulnerabilities

npm ls then marked the override explicitly:

eresolve-repro@1.0.0
├── react-dom@16.14.0
└── react@19.3.0 overridden

This is the more deliberate fix: it's visible in version control, scoped to the one dependency that needed it, and doesn't quietly disable peer checks for the rest of the project the way --legacy-peer-deps does. Like the flags above, it only changes what npm resolves; it does not verify that react-dom@16's code actually runs correctly against react@19 at runtime. That's a separate compatibility question npm cannot check for you.

7. Peer-dependency conflicts as a sub-topic

ERESOLVE is just how npm reports a peer dependency conflict at install time. The pattern is always the same shape: package X peer-depends on a range of package Y, something else in your tree wants a different Y, and the ranges don't intersect. Common real-world triggers we've seen described in the same shape as our test:

In all of these the fixes are the same three options measured above, in order of preference: upgrade the conflicting package if a compatible release exists, add a scoped overrides entry, or fall back to --legacy-peer-deps/--force only once you've checked the actual code paths involved still work.

8. How to fix it, in order

Frequently asked questions

What does ERESOLVE unable to resolve dependency tree mean?

npm found two packages in your project that need incompatible versions of the same dependency and refuses to guess which one you want. We measured this with react@19.3.0 installed next to react-dom@16.14.0, which requires react@^16.14.0 as a peer.

Does npm install --legacy-peer-deps actually fix the conflict?

It makes npm skip peer dependency checks entirely, the way npm 6 behaved. In our test it installed both conflicting packages with no warning at all. It doesn't resolve the conflict or verify the packages work together; it just stops checking.

What's the difference between --force and --legacy-peer-deps?

In our test both produced the same installed tree, but --force printed the exact conflicting versions as a warning ('npm warn ERESOLVE overriding peer dependency') while --legacy-peer-deps printed nothing. --force is the more visible, more honest-about-what-happened option of the two.

Is the package.json overrides field better than --force?

For a known, specific conflict, yes. Adding an overrides entry for just the one dependency let a plain npm install succeed with no flags and no warnings, and npm ls marked the forced version as 'overridden' so it stays visible in the tree. --force and --legacy-peer-deps apply blanket exceptions to the whole install instead.

Will npm warn me if the forced versions don't actually work together?

No. In all three cases we tested (--legacy-peer-deps, --force, overrides) npm only resolves version numbers; it does not run any code. A successful install is not proof react-dom@16 works correctly with react@19 — you still need to test the app.

Written with AI assistance. Measured on 2026-10-02 with npm 11.19.0 and Node.js 24.21.0, installing react@19.3.0 alongside react-dom@16.14.0 (which peer-depends on react@^16.14.0) from the public npm registry. Claims about npm 6's non-strict peer behaviour are per npm's own release notes, not measured here (only npm 11 was available on this box). PlainHeaders is our browser extension; npm and Node.js are free.