Fix: pnpm Peer Dependency Errors (Missing or Incompatible Peer Dependencies)
Quick Answer
How to fix pnpm peer dependency errors — why pnpm is stricter than npm about peer deps, how to resolve missing peers, configure peerDependencyRules, and handle incompatible version ranges.
The Error
Running pnpm install fails or warns with:
WARN Issues with peer dependencies found
.
└─┬ some-library 2.0.0
├── ✕ missing peer react@">=17.0.0"
└── ✕ missing peer react-dom@">=17.0.0"Or an error that blocks installation:
ERROR unmet peer react@"^17.0.0": found 18.2.0Or after installing:
WARN 4 packages have unmet peer dependenciesOr a package works with npm but fails with pnpm:
Cannot find module 'react' from 'node_modules/some-library/dist/index.js'Why This Happens
pnpm is stricter about peer dependencies than npm or yarn by default. In npm v7+, peer dependencies are automatically installed. pnpm takes a different approach:
- Peer dependencies are not automatically installed — pnpm expects the consuming project to provide peer dependencies explicitly.
- Isolated
node_modulesstructure — pnpm uses a content-addressable store and symlinks. Packages cannot accidentally access peer dependencies through hoisting (as they can with npm’s flatnode_modules). - Strict mode by default — pnpm reports peer dependency issues as errors in some configurations.
This is intentional. pnpm’s strictness prevents “phantom dependencies” — packages that work in development (because a peer is accidentally hoisted) but break in production.
Fix 1: Install the Missing Peer Dependencies
The simplest fix — install what the packages require:
# pnpm tells you what is missing:
# ✕ missing peer react@">=17.0.0"
# ✕ missing peer react-dom@">=17.0.0"
pnpm add react react-domFor development-only peer deps (testing libraries, build tools):
pnpm add -D @testing-library/react @testing-library/jest-domCheck what peer deps a package requires before installing it:
pnpm info some-library peerDependencies
# or
pnpm why some-libraryAfter installing, verify peers are resolved:
pnpm install
# Should show no WARN lines about peer dependenciesFix 2: Configure peerDependencyRules in .npmrc
For peer dependency warnings you cannot resolve (e.g., an incompatible version range from a dependency you do not control), configure pnpm to suppress or allow them:
# .npmrc
# Silence all peer dependency warnings (not recommended for production)
strict-peer-dependencies=false
# Allow specific peer dependency mismatches
# Format: package@range → allowed version rangeUse peerDependencyRules in package.json:
{
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"webpack",
"@babel/core"
],
"allowedVersions": {
"react": "18",
"eslint": "8 || 9"
},
"allowAny": [
"supports-color"
]
}
}
}Explanation of each field:
ignoreMissing— suppresses “missing peer” warnings for these packages (you know you do not need them).allowedVersions— tells pnpm that the installed version satisfies the peer requirement even if semver says otherwise. Use when you are confident the package works with your version.allowAny— allows any version of the package to satisfy the peer requirement.
{
"pnpm": {
"peerDependencyRules": {
"allowedVersions": {
"react": "18.2.0",
"react-dom": "18.2.0",
"some-library>react": "18"
}
}
}
}The some-library>react format allows specifying the rule only for a specific package’s peer dependency — instead of globally.
Fix 3: Fix the “Cannot Find Module” Error at Runtime
pnpm’s isolated node_modules means a package cannot accidentally resolve peer dependencies through hoisting. If a package fails to find its peer at runtime:
Check how pnpm resolves the package:
pnpm why react
# Shows which packages depend on react and how it is resolvedUse shamefully-hoist as a last resort (mimics npm behavior):
# .npmrc
shamefully-hoist=trueThis hoists all packages to the top-level node_modules like npm does. It defeats pnpm’s isolation benefits but fixes packages that rely on hoisting:
# Delete existing node_modules and reinstall with hoisting
rm -rf node_modules
pnpm installWarning:
shamefully-hoist=trueis a workaround. It masks real dependency problems and makes your project fragile. Use it temporarily while you report or fix the upstream package, then remove it.
More targeted approach — hoist specific packages:
# .npmrc — hoist only specific packages instead of everything
hoist-pattern[]=*react*
hoist-pattern[]=*emotion*Fix 4: Handle Peer Dependencies in Monorepos
In a pnpm workspace, peer dependencies must be installed at the right level:
# pnpm-workspace.yaml
packages:
- 'packages/*'
- 'apps/*'// packages/ui/package.json
{
"name": "@myapp/ui",
"peerDependencies": {
"react": ">=17",
"react-dom": ">=17"
},
"devDependencies": {
"react": "18.2.0", // Install as devDep for testing the package itself
"react-dom": "18.2.0"
}
}// apps/web/package.json
{
"name": "web",
"dependencies": {
"@myapp/ui": "workspace:*",
"react": "18.2.0", // Provides react to @myapp/ui as a peer
"react-dom": "18.2.0"
}
}Install workspace packages correctly:
# From the root
pnpm install
# Add a dependency to a specific workspace package
pnpm add lodash --filter @myapp/ui
# Add a dev dependency to the root
pnpm add -D -w typescriptCheck peer dependency status across the workspace:
pnpm -r exec -- pnpm ls --depth 0Fix 5: Fix Version Range Conflicts
When two packages require incompatible versions of the same peer:
✕ package-a requires react@"^16.0.0"
✕ package-b requires react@"^18.0.0"
# Cannot satisfy both with a single react versionOption A — use allowedVersions to override (if you know it works):
{
"pnpm": {
"peerDependencyRules": {
"allowedVersions": {
"package-a>react": "18",
"package-b>react": "18"
}
}
}
}Option B — upgrade package-a to a version that supports React 18:
pnpm outdated # Shows available upgrades
pnpm update package-a --latestOption C — replace package-a with a React 18-compatible alternative.
Option D — use overrides to force a specific version:
{
"pnpm": {
"overrides": {
"react": "18.2.0", // Forces all packages to use React 18.2.0
"react-dom": "18.2.0"
}
}
}Warning: Overrides force version resolution globally. A package requiring React 16 will receive React 18 — this may or may not work depending on the package’s actual compatibility. Test thoroughly.
Fix 6: Diagnose Peer Dependency Issues
See a full report of peer dependency issues:
pnpm install --strict-peer-dependencies 2>&1 | grep -E "WARN|ERROR|peer"List all packages with unmet peers:
pnpm ls --depth Infinity 2>&1 | grep "unmet peer"Check why a specific package is installed:
pnpm why some-package
# Shows the dependency chain that requires some-packageDry run to see what pnpm will install:
pnpm add some-library --dry-runFix 7: Migrate from npm to pnpm Without Breaking Peer Deps
When migrating an existing project from npm to pnpm:
# 1. Remove npm artifacts
rm -rf node_modules package-lock.json
# 2. Install pnpm
npm install -g pnpm
# 3. Import from package.json (generates pnpm-lock.yaml)
pnpm import # Converts package-lock.json or yarn.lock to pnpm-lock.yaml
# 4. Install
pnpm install
# 5. Check for peer dep warnings
# Address each warning or add to peerDependencyRulesAdd a .npmrc with sensible defaults for migrated projects:
# .npmrc
auto-install-peers=true # Automatically install missing peers (pnpm 8+)
strict-peer-dependencies=false # Warn but don't error on peer dep issues during migrationauto-install-peers=true (pnpm 8 default) makes pnpm behave more like npm by automatically installing missing peer dependencies. This is the easiest fix for most migration issues.
Still Not Working?
Check your pnpm version. pnpm 8 changed peer dependency behavior significantly — auto-install-peers defaults to true in pnpm 8, which resolves many issues automatically:
pnpm --version
# If < 8, upgrade:
npm install -g pnpm@latestCheck for conflicting .npmrc files. A .npmrc in your home directory (~/.npmrc) may conflict with the project .npmrc:
cat ~/.npmrc
cat .npmrcRegenerate the lockfile if it is corrupted:
rm pnpm-lock.yaml
pnpm installCheck if the issue is specific to CI. CI environments sometimes have different Node.js versions or global packages that affect peer resolution. Pin Node.js version in CI:
# .github/workflows/ci.yml
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'For related package manager issues, see Fix: npm ERR! peer dep conflict and Fix: npm ERESOLVE Unable to Resolve Dependency Tree.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Express req.body Is undefined
How to fix req.body being undefined in Express — missing body-parser middleware, wrong Content-Type header, middleware order issues, and multipart form data handling.
Fix: Git Keeps Asking for Username and Password
How to fix Git repeatedly prompting for credentials — credential helper not configured, HTTPS vs SSH, expired tokens, macOS keychain issues, and setting up a Personal Access Token.
Fix: Node.js Crashing with UnhandledPromiseRejection (--unhandled-rejections)
How to fix Node.js UnhandledPromiseRejectionWarning and process crashes — why unhandled promise rejections crash Node.js 15+, how to add global handlers, find the source of the rejection, and fix async error handling.
Fix: Poetry Dependency Conflict (SolverProblemError / No Solution Found)
How to fix Poetry dependency resolution errors — SolverProblemError when adding packages, conflicting version constraints, how to diagnose dependency trees, and workarounds for incompatible packages.