Skip to content

Fix: npm ERR! Could not resolve peer dependency conflict

FixDevs ·

Quick Answer

How to fix the npm ERR! Could not resolve peer dependency conflict error. Covers --legacy-peer-deps, --force, npm overrides, peerDependenciesMeta, React version conflicts, and debugging with npm ls.

The Error

You run npm install and get hit with this:

npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: my-app@1.0.0
npm ERR! Found: react@18.3.1
npm ERR! node_modules/react
npm ERR!   react@"^18.3.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.8.0 || ^17.0.0" from react-beautiful-dnd@13.1.1
npm ERR! node_modules/react-beautiful-dnd
npm ERR!   react-beautiful-dnd@"^13.1.1" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: react@17.0.2
npm ERR! node_modules/react
npm ERR!   peer react@"^16.8.0 || ^17.0.0" from react-beautiful-dnd@13.1.1
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 critical line is Could not resolve dependency. npm is telling you that two packages in your project demand different versions of the same dependency, and it cannot satisfy both at once.

This error blocks installation entirely. Nothing gets installed until you resolve it.

Why This Happens

Peer dependencies let a package declare that it expects the host project to provide a certain dependency at a compatible version. The package does not bundle it. Instead, it relies on whatever version you have installed.

A peer dependency conflict happens when two or more packages in your tree disagree on which version of that shared dependency is acceptable. Package A says it needs react@^17.0.0. Package B says it needs react@^18.0.0. There is no single version of React that satisfies both ranges.

npm 7+ Changed the Rules

Before npm 7, peer dependency conflicts were warnings. npm printed a message and installed everything anyway. Starting with npm 7, these conflicts became hard errors. If npm cannot build a valid dependency tree where every peer dependency requirement is met, installation fails.

This was an intentional decision. The old behavior led to silent runtime failures: packages would load incompatible versions of shared libraries, causing crashes that were extremely difficult to trace back to a version mismatch. The stricter behavior forces you to deal with conflicts at install time rather than at 2 AM in production.

Common Triggers

  • Upgrading React (or another major framework) while third-party libraries still declare the old version as a peer dependency.
  • Adding a new package that depends on a different major version of something already in your tree.
  • Upgrading npm itself (or Node.js, which bundles npm). A project that installed fine under npm 6 may fail under npm 9 because the same conflicts were always there, just hidden.
  • Stale lockfiles where package-lock.json was generated under different conditions and now contains resolution data that conflicts with current requirements.

If you are seeing the broader ERESOLVE unable to resolve dependency tree variant, the underlying cause is the same. See Fix: npm ERR! ERESOLVE unable to resolve dependency tree for additional context on that error message.

Fix 1: Use the --legacy-peer-deps Flag

This tells npm to revert to npm 6 behavior and skip peer dependency resolution entirely:

npm install --legacy-peer-deps

npm will install all packages but will not attempt to ensure peer dependency ranges are satisfied. If a library says it needs react@^17.0.0 and you have React 18, npm will shrug and move on.

To make this permanent for your project, add it to .npmrc in your project root:

legacy-peer-deps=true

This ensures every developer on the team (and your CI pipeline) uses the same behavior without remembering to pass the flag.

When this is safe: Most of the time. Peer dependency ranges are often overly conservative. A library that declares react@^17.0.0 frequently works fine with React 18 because React maintains strong backward compatibility. The peer dependency just has not been updated.

When this is risky: If the library genuinely uses APIs that were removed or changed in the newer version. In that case, you will get runtime errors instead of install-time errors.

Fix 2: Use the --force Flag

npm install --force

This is more aggressive than --legacy-peer-deps. It forces npm to bypass all dependency resolution checks, overwrite existing packages if needed, and install everything regardless of conflicts.

Warning: --force can lead to duplicate copies of packages in your node_modules tree and unpredictable behavior. It is a last resort, not a first choice. Try --legacy-peer-deps first.

The key difference: --legacy-peer-deps ignores peer dependency requirements entirely. --force still tries to resolve them but will accept broken resolutions and push through. In practice, --force can cause npm to install multiple copies of the same package at different versions, which inflates your node_modules size and can cause subtle bugs with libraries that expect a single instance (like React).

Common Mistake: Using --force in CI pipelines as a permanent fix. This masks real dependency problems and can introduce non-deterministic builds. If you need a workaround in CI, prefer --legacy-peer-deps and document why.

Fix 3: Fix Version Ranges in package.json

This is the proper fix. Read the error output carefully. npm tells you exactly which packages conflict and what versions they expect.

Given an error like:

  • Found: react@18.3.1
  • Peer requires: react@"^16.8.0 || ^17.0.0" from react-beautiful-dnd@13.1.1

You have two paths:

Option A: Downgrade the shared dependency

If the conflicting library is critical and you are not using features exclusive to the newer version:

npm install react@17 react-dom@17

This satisfies the peer dependency range. Make sure to also adjust any other packages tied to the major version (like react-dom, @types/react, etc.).

Option B: Upgrade the conflicting library

Check if a newer version of the library supports your dependency version:

npm view react-beautiful-dnd versions
npm view react-beautiful-dnd peerDependencies

If the latest version has widened its peer dependency range to include your version, upgrade:

npm install react-beautiful-dnd@latest

If the library is unmaintained and stuck on old peer dependencies, consider switching to an actively maintained alternative. For example, react-beautiful-dnd has been largely superseded by @hello-pangea/dnd, which supports React 18 natively.

Fix 4: Use npm Overrides to Force Resolution

When you know a library works with a version outside its declared peer range, you can tell npm to override the resolution. Add an overrides field to your package.json:

{
  "dependencies": {
    "react": "^18.3.0",
    "react-beautiful-dnd": "^13.1.1"
  },
  "overrides": {
    "react-beautiful-dnd": {
      "react": "$react"
    }
  }
}

The $react reference means “use whatever version of react is specified in the top-level dependencies.” This forces react-beautiful-dnd to accept your React 18 installation.

For a broader override that applies across all packages:

{
  "overrides": {
    "react": "18.3.1"
  }
}

This pins react to a single version everywhere in the tree. Every package that depends on React will get 18.3.1, regardless of what its peer dependency range says.

After adding overrides, delete the lockfile and reinstall:

rm -rf node_modules package-lock.json
npm install

Note: The overrides field requires npm 8.3 or later. Check your version with npm --version. If you are behind, upgrade with npm install -g npm@latest.

If you hit a 404 error while installing packages, that is a separate issue. See Fix: npm ERR! code E404 for help with registry problems.

Fix 5: Update the Conflicting Packages

Before reaching for overrides or flags, check if simply updating your dependencies resolves the conflict. Outdated packages are the most common cause of peer dependency mismatches.

List outdated packages:

npm outdated

This shows a table of packages with their current, wanted, and latest versions. Focus on the packages mentioned in the error output.

Update a specific package:

npm update some-library

Or install the latest major version explicitly:

npm install some-library@latest

If multiple packages are outdated, update them together to avoid creating new conflicts:

npm update

After updating, run npm install again to verify the conflict is gone. Sometimes updating one package resolves the conflict, but reveals a new one with a different package. Work through them one at a time.

Pro Tip: Use npm outdated --long to see the package type (dependency, devDependency) and homepage URL. The homepage often links to a changelog where you can quickly check if peer dependency ranges were updated in a recent release.

If your install script fails during the build step after resolving dependencies, that is a different error. See Fix: npm ERR! code ELIFECYCLE for troubleshooting build failures.

Fix 6: Use peerDependenciesMeta to Mark Peers as Optional

If you are a package author and your package has a peer dependency that is not strictly required, you can mark it as optional. This prevents the conflict from blocking installation for your users.

In your package’s package.json:

{
  "peerDependencies": {
    "react": "^17.0.0 || ^18.0.0",
    "react-native": ">=0.60"
  },
  "peerDependenciesMeta": {
    "react-native": {
      "optional": true
    }
  }
}

With optional: true, npm will not throw an error if react-native is missing or at an incompatible version. It will still be used if present, but its absence will not block installation.

This is useful for libraries that support multiple environments (web and React Native, for example) where not every peer dependency applies to every user.

As a consumer, you cannot directly modify a library’s peerDependenciesMeta. But you can achieve a similar effect using overrides (Fix 4) or by patching the package with patch-package:

npx patch-package some-library

This creates a patch file that modifies the library’s package.json after installation. It is a more surgical approach than a global override.

Fix 7: Fix React Version Conflicts (React 17 vs 18)

React version mismatches are the single most common cause of peer dependency conflicts. This deserves its own section because the fix depends on the specific situation.

Scenario: You upgraded to React 18 and libraries broke

Many popular libraries released React 18 support months after React 18 launched. If you see errors like:

npm ERR! peer react@"^17.0.0" from some-library@x.y.z

First, check if the library has a newer version with React 18 support:

npm view some-library peerDependencies --json

If the latest version still only supports React 17, check the library’s GitHub issues. There may be a beta or release candidate with React 18 support:

npm view some-library versions --json

Look for versions tagged as next, beta, or rc.

React ecosystem packages (react-dom, @types/react, react-test-renderer, @testing-library/react) all need to be on compatible versions. A common mistake is upgrading react but forgetting react-dom:

npm install react@18 react-dom@18

For TypeScript projects, also align the type definitions:

npm install @types/react@18 @types/react-dom@18

Scenario: You need React 17 and 18 in the same project

This is rare but happens in micro-frontend setups. npm does not support installing two versions of the same package at the top level. You would need to use package aliases:

npm install react-17@npm:react@17 react-18@npm:react@18

This installs React 17 as react-17 and React 18 as react-18. You then configure each micro-frontend to import from the correct alias. This is advanced and introduces complexity. Only go down this path if you genuinely need both versions.

For missing file errors during React project setup, check Fix: npm ENOENT no such file or directory.

Fix 8: Use npm ls to Debug the Dependency Tree

When the error output is not enough to understand the conflict, use npm ls to inspect the full dependency tree.

Show all instances of a specific package:

npm ls react

Output looks like:

my-app@1.0.0
+-- react@18.3.1
+-- react-beautiful-dnd@13.1.1
|   `-- react@"^16.8.0 || ^17.0.0" (UNMET PEER DEPENDENCY)
+-- @testing-library/react@14.0.0
|   `-- react@"^18.0.0" (peer satisfied)

The UNMET PEER DEPENDENCY label pinpoints exactly where the conflict lives.

For a more detailed view:

npm ls react --all

This shows the entire tree including transitive dependencies. It is verbose but reveals deep conflicts that are not obvious from the top-level error.

To check the dependency tree before installing (useful for testing whether adding a new package would cause a conflict):

npm install some-new-package --dry-run

The --dry-run flag simulates the installation without writing anything to node_modules. If there is a peer dependency conflict, you will see the error without having modified your project.

You can also check what peer dependencies a package requires before installing it:

npm view some-package peerDependencies

This outputs the peer dependency ranges so you can check compatibility before committing to the install.

For packages that seem to disappear from the registry entirely, see Fix: npm WARN deprecated for guidance on dealing with deprecated and removed packages.

Still Not Working?

Monorepo Workspaces

In monorepo setups using npm workspaces, peer dependency resolution works differently. npm hoists dependencies to the root node_modules by default, but individual workspace packages may declare conflicting peer requirements.

Key rules for npm workspaces:

  • Overrides must go in the root package.json. Overrides declared in workspace packages are ignored.
  • Use --workspace to install into a specific workspace without affecting others:
npm install some-package --workspace=packages/my-app
  • If hoisting causes conflicts, you can prevent specific packages from being hoisted by adding a .npmrc in the workspace package directory:
hoist=false

npm-shrinkwrap.json Issues

If your project uses npm-shrinkwrap.json (a lockfile that ships with published packages), it can lock dependency resolutions to versions that conflict with your current setup. Unlike package-lock.json, shrinkwrap files are not ignored when your package is installed as a dependency.

Try removing the shrinkwrap and regenerating:

rm npm-shrinkwrap.json
npm install
npm shrinkwrap

Switching to Yarn or pnpm

If the npm resolution algorithm cannot find a valid tree for your dependencies, a different package manager might handle it. Both Yarn and pnpm resolve peer dependencies differently.

pnpm uses a strict content-addressable store and symlinks, which avoids many hoisting-related conflicts:

npx pnpm import   # converts package-lock.json to pnpm-lock.yaml
npx pnpm install

Yarn (v1) uses resolutions instead of overrides:

{
  "resolutions": {
    "react": "18.3.1"
  }
}

Yarn Berry (v2+) has even more control through its Plug’n’Play resolution strategy, which eliminates node_modules entirely and can resolve conflicts that trip up npm.

Switching package managers is a significant change. Test thoroughly before committing, and make sure your CI pipeline and deployment scripts are updated. But if you have been fighting npm resolution errors for hours, it is worth trying.

Last Resort: Check the Debug Log

npm writes a detailed log file for every failed operation. The path is printed at the bottom of the error output:

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/user/.npm/_logs/2026-03-09T10_00_00_000Z-debug-0.log

Open that file. It contains the full resolution algorithm trace, showing every package npm tried to resolve and why it failed. Search for ERESOLVE in the log to jump to the relevant section. This often reveals transitive dependencies (dependencies of dependencies) causing the conflict, which are not visible in the summary error output.

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