Skip to content

Fix: pnpm Peer Dependency Errors (Missing or Incompatible Peer Dependencies)

FixDevs ·

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.0

Or after installing:

 WARN  4 packages have unmet peer dependencies

Or 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_modules structure — pnpm uses a content-addressable store and symlinks. Packages cannot accidentally access peer dependencies through hoisting (as they can with npm’s flat node_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-dom

For development-only peer deps (testing libraries, build tools):

pnpm add -D @testing-library/react @testing-library/jest-dom

Check what peer deps a package requires before installing it:

pnpm info some-library peerDependencies
# or
pnpm why some-library

After installing, verify peers are resolved:

pnpm install
# Should show no WARN lines about peer dependencies

Fix 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 range

Use 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 resolved

Use shamefully-hoist as a last resort (mimics npm behavior):

# .npmrc
shamefully-hoist=true

This 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 install

Warning: shamefully-hoist=true is 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 typescript

Check peer dependency status across the workspace:

pnpm -r exec -- pnpm ls --depth 0

Fix 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 version

Option 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 --latest

Option 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-package

Dry run to see what pnpm will install:

pnpm add some-library --dry-run

Fix 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 peerDependencyRules

Add 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 migration

auto-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@latest

Check for conflicting .npmrc files. A .npmrc in your home directory (~/.npmrc) may conflict with the project .npmrc:

cat ~/.npmrc
cat .npmrc

Regenerate the lockfile if it is corrupted:

rm pnpm-lock.yaml
pnpm install

Check 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.

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