Introduction
Starting with npm v7, peer dependencies are installed by default and strictly resolved. When two packages require different major versions of the same peer dependency, npm refuses to install with ERESOLVE unable to resolve dependency tree. This is more strict than npm v6 and Yarn but prevents incompatible package combinations. Common conflicts occur with React, TypeScript, ESLint, and testing libraries.
Symptoms
npm ERR! ERESOLVE unable to resolve dependency treenpm ERR! Could not resolve dependency: peer react@"^16.8.0" from react-dom@16.14.0npm ERR! Conflicting peer dependency: react@18.2.0npm installfails after adding a new package- Works with
--legacy-peer-depsbut not with default settings
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@18.2.0
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@"^16.8.0" from react-native-modal@13.0.0
npm ERR! node_modules/react-native-modal
npm ERR! react-native-modal@"^13.0.0" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-depsCommon Causes
- Upgrading React from v16 to v18 while some packages only support v16
- Mixing ESLint v8 and v9 plugins with different peer requirements
- Testing library version mismatches
- Monorepo workspaces with conflicting peer dependencies
- Third-party packages with outdated peer dependency declarations
Step-by-Step Fix
- 1.Understand the conflict tree:
- 2.```bash
- 3.# Show why npm cannot resolve dependencies
- 4.npm install 2>&1 | head -50
# Show dependency tree npm ls react npm ls eslint
# Find which packages require which versions npm explain react ```
- 1.Upgrade the conflicting package:
- 2.```bash
- 3.# Check for updates to the package with strict peer deps
- 4.npm outdated react-native-modal
- 5.npm install react-native-modal@latest
- 6.# Newer versions may support React 18
- 7.
` - 8.Use npm overrides to force a version:
- 9.```json
- 10.// package.json
- 11.{
- 12."overrides": {
- 13."react": "$react",
- 14."react-dom": "$react-dom"
- 15.},
- 16."dependencies": {
- 17."react": "^18.2.0",
- 18."react-dom": "^18.2.0",
- 19."react-native-modal": "^13.0.0"
- 20.}
- 21.}
// "$react" resolves to the version in dependencies // This forces all packages to use React 18 ```
- 1.Use --legacy-peer-deps (temporary workaround):
- 2.```bash
- 3.# Skip peer dependency resolution (npm v6 behavior)
- 4.npm install --legacy-peer-deps
# Or set permanently in .npmrc echo "legacy-peer-deps=true" >> ~/.npmrc
# WARNING: This may install incompatible package combinations # Only use when you have verified the packages work together ```
- 1.Use npm install --force for one-time resolution:
- 2.```bash
- 3.# Force installation despite conflicts
- 4.npm install --force
# This creates a nested node_modules for the conflicting package # May result in duplicate packages in node_modules ```
- 1.Configure for monorepo workspaces:
- 2.```json
- 3.// Root package.json
- 4.{
- 5."workspaces": ["packages/*"],
- 6."overrides": {
- 7."react": "^18.2.0",
- 8."typescript": "^5.3.0"
- 9.}
- 10.}
// npm will hoist these versions to the root // All workspaces share the same peer dependency versions ```
Prevention
- Keep peer dependencies updated when upgrading major versions
- Use
npm overridesto enforce consistent versions across the tree - Add
npm installto CI to catch conflicts before deployment - Check package peer dependency compatibility before installing
- Prefer
--legacy-peer-depsonly for packages known to be compatible - Use
npm explain <package>to understand dependency chains - Consider using pnpm which handles peer dependencies more flexibly