Skip to content

Fix: npm ERR! ERESOLVE unable to resolve dependency tree

FixDevs · (Updated: )

Part of:  JavaScript & TypeScript Errors

Quick Answer

How to fix the ERESOLVE unable to resolve dependency tree error in npm. Covers root causes, peer dependency conflicts, --legacy-peer-deps, --force, npm overrides, and edge cases with React 18, TypeScript, and monorepos.

The Error

When running npm install, you get something like this:

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR!   react@"^18.2.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^17.0.0" from [email protected]
npm ERR! node_modules/some-library
npm ERR!   some-library@"^2.3.1" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

The key lines are the Found: and Could not resolve dependency: blocks. They tell you exactly which packages are in conflict and what versions each side expects.

Why This Happens

Peer dependencies are a way for a package to say “I don’t bundle this dependency myself — I expect the project that installs me to provide it.” A common example: a React component library declares react as a peer dependency because it expects your project to already have React installed. The contract is “we both need to use the same React instance, so you control which version.”

When two or more packages disagree on which version of a shared peer dependency should be installed, npm has no safe choice. Installing one version breaks the contract with the other package. Refusing to install lets you decide which side to satisfy. This is the situation npm describes as ERESOLVE unable to resolve dependency tree.

The strictness behavior changed sharply between major npm versions. Before npm 7, the same conflict would have been a warning you could safely ignore. After npm 7, it became a hard error. Most teams hit this error for the first time after upgrading Node.js (which bundles a newer npm) and being confused why a project that worked yesterday is broken today.

Why npm 7+ Is Stricter

This is the core of the issue. Before npm 7, peer dependency conflicts were treated as warnings. npm would print a message and move on. Starting with npm 7 (released October 2020 alongside Node.js 15) and continuing in npm 8, 9, and 10, peer dependency conflicts are treated as errors that block installation entirely.

The npm team made this change because silently installing incompatible peer dependencies caused hard-to-debug runtime errors. The stricter behavior forces you to address the conflict upfront rather than discovering it later when your app crashes.

If your project worked fine before upgrading npm (or before upgrading Node.js, which bundles a newer npm), this is almost certainly why.

A Short History of --legacy-peer-deps

The --legacy-peer-deps flag did not exist before npm 7 because there was no “new” behavior to opt out of. npm 7 introduced it specifically as an escape hatch for the community pain caused by the new strict behavior. The flag tells npm: “use the npm 6 algorithm for resolving peer dependencies — print warnings but do not fail.”

It was originally pitched as a temporary stopgap. Five years later, it is still widely used because many large ecosystems (Storybook plugins, older Material UI versions, React Native dependency chains, jest plugins) ship overly narrow peer-dep ranges that the maintainers never updated. The flag works, but it suppresses real signals along with the false ones.

overrides (npm 8.3, January 2022) and Yarn’s resolutions field were the longer-term answers: instead of disabling the check globally, you tell npm exactly which version of the shared peer to use everywhere. This is the recommended approach when --legacy-peer-deps would mask a problem you actually want to fix.

Fix

Solution 1: Use --legacy-peer-deps

This tells npm to use the old npm 6 behavior and ignore peer dependency conflicts:

npm install --legacy-peer-deps

To make this the default for your project, create or edit an .npmrc file in your project root:

legacy-peer-deps=true

This is the quickest fix and is safe in most cases. The peer dependency mismatch often doesn’t cause actual runtime issues — many libraries work fine across a wider range of versions than their peer dependency declarations suggest.

When to avoid this: If the conflicting packages truly are incompatible at runtime (e.g., a library uses an API that was removed in the version you have installed), this will just defer the problem.

Solution 2: Use --force

npm install --force

This is more aggressive than --legacy-peer-deps. It forces npm to fetch packages even if they would cause conflicts, and it will also overwrite packages that were previously installed with a different version. It still installs the conflicting dependencies but bypasses the resolution checks.

Use --legacy-peer-deps first. Only reach for --force if that doesn’t work.

Why this matters: Before npm 7, peer dependency conflicts were silent warnings that often led to mysterious runtime crashes. The stricter behavior in npm 7+ forces you to confront version mismatches during install rather than discovering them in production at 2 AM.

Solution 3: Resolve the Conflict in package.json

This is the correct long-term fix. Read the error output carefully — it tells you exactly which versions conflict.

For example, if the error says:

You have two options:

A. Upgrade the library that has the outdated peer dependency:

npm install some-library@latest

Check the library’s changelog or npm page to see if a newer version supports your current dependency.

B. Downgrade the dependency to match what the library expects:

npm install react@17 react-dom@17

Only do this if you’re not relying on features from the newer version.

Solution 4: Use npm overrides

If you know the library works fine with your version despite the declared peer dependency, you can override the resolution. In your package.json, add:

{
  "overrides": {
    "some-library": {
      "react": "$react"
    }
  }
}

The $react syntax tells npm to use whatever version of react is defined in your top-level dependencies. This forces some-library to accept your project’s version of React.

For more targeted overrides:

{
  "overrides": {
    "react": "18.2.0"
  }
}

This sets a global override for react across all nested dependencies.

Note: overrides was introduced in npm 8.3. If you’re on an older version, upgrade npm first: npm install -g npm@latest.

Solution 5: Delete node_modules and package-lock.json

Sometimes the lockfile itself contains stale resolution data that causes the conflict. Start fresh:

rm -rf node_modules package-lock.json
npm install

On Windows (Command Prompt):

rmdir /s /q node_modules
del package-lock.json
npm install

This forces npm to resolve the entire dependency tree from scratch. If the conflict was caused by a stale lockfile rather than an actual version mismatch, this alone can fix it. If you get a Cannot find module error after reinstalling, see Fix: Error Cannot find module.

Common Mistake: Making legacy-peer-deps=true permanent in .npmrc and then forgetting about it. This silences all future peer dependency conflicts, hiding real incompatibilities. Use it as a temporary workaround while you work toward a proper resolution.

Edge Cases

React 18 with Libraries Expecting React 17

This is by far the most common instance of this error. Many popular libraries (older versions of Material UI, React Router v5, some testing libraries) declared "react": "^17.0.0" as a peer dependency before React 18 was released.

Best approach: Check if there’s an updated version of the library that supports React 18. Most actively maintained libraries have released updates. If not, --legacy-peer-deps is safe here — React 18 is backward-compatible with React 17 APIs in nearly all cases.

React 19 With Libraries Expecting React 18

A second wave of this error landed when React 19 shipped in December 2024. A long tail of libraries — React Native libraries, animation libraries, older form libraries — pinned "react": "^18.0.0" and have not yet bumped their peer range. The same workarounds apply: try npm install <lib>@latest first, then overrides, and only fall back to --legacy-peer-deps if the maintainer has not shipped an update.

Conflicting TypeScript Versions

Some packages pin specific TypeScript version ranges as peer dependencies. If you see conflicts involving typescript, check which versions each package requires. Related TypeScript issues like missing module type declarations can also surface after resolving version conflicts.

npm ls typescript

Often you can resolve this by pinning a TypeScript version that satisfies all parties. For example, if one package wants typescript@^4.7.0 and another wants typescript@^4.9.0, installing [email protected] satisfies both.

Monorepos

In monorepo setups (using npm workspaces, Nx, or Turborepo), peer dependency conflicts are more likely because multiple packages may declare different versions of the same dependency.

For npm workspaces, set overrides at the root package.json level. Overrides defined in workspace packages are ignored — only the root-level overrides take effect.

{
  "workspaces": ["packages/*"],
  "overrides": {
    "typescript": "5.3.3"
  }
}

If you’re using Yarn instead of npm, the equivalent feature is resolutions:

{
  "resolutions": {
    "typescript": "5.3.3"
  }
}

Still Not Working?

  1. Read the full error output. The npm ERR! lines contain the exact package names and version ranges in conflict. The fix depends on which packages are involved.

  2. Check the npm-debug.log file (path is printed at the bottom of the error). It contains the full dependency resolution tree and can reveal transitive (nested) conflicts that aren’t obvious from the summary.

  3. Inspect your dependency tree:

    npm ls --all

    This shows every installed package and its dependencies. Look for version mismatches and duplicates.

  4. Try a different package manager. If you’re stuck, pnpm and Yarn handle peer dependencies differently and may resolve the conflict automatically. You can try without committing to a switch:

    npx pnpm install

    pnpm uses a stricter content-addressable store and surfaces a different but related error when peer deps disagree. If you switch and still hit problems, see Fix: pnpm peer dependency error.

  5. Open an issue upstream. If a library’s peer dependency range is too narrow and the library actually works with newer versions, file an issue or PR asking the maintainer to widen the range. This helps everyone.

  6. Check that npm itself is current. Some ERESOLVE messages improved dramatically between npm 8 and npm 10 — the modern output names every package in the conflict chain, not just the immediate parent. Update with npm install -g npm@latest. If you previously installed npm globally with sudo and now hit EACCES, see Fix: EACCES permission denied when installing npm packages globally.

  7. Check Node’s bundled npm vs your installed npm. If you have nvm or asdf managing Node, each Node version ships its own npm. Switching Node versions can swap npm 8 for npm 10 without warning. Run node --version && npm --version to confirm the pair you are actually using before debugging further.

  8. Look for a transitive peer conflict. Sometimes the named package in the error is itself fine — the real conflict is between two of its dependencies. Run npm explain <package> on the package the error names to see the full chain that pulled it in.


Related: If you’re getting permission errors when installing npm packages globally, see Fix: EACCES permission denied when installing npm packages globally.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles