🔧 Error Fixes
· 2 min read
Last updated on

pnpm: Module Not Found — Shamefully Hoist Fix


Module not found — package exists in node_modules but can't be resolved

What causes this

pnpm uses a strict node_modules structure where packages can only access their declared dependencies. This is correct behavior — it prevents “phantom dependencies” (using packages you didn’t explicitly install). However, some packages are poorly written and rely on npm/yarn’s flat node_modules structure to access undeclared dependencies.

Common scenarios:

  • A package imports a peer dependency it didn’t declare
  • A Webpack/Vite plugin tries to resolve modules from the project root
  • ESLint or Prettier plugins that expect flat node_modules
  • Monorepo packages accessing dependencies from the root

Instead of hoisting everything, only hoist the packages that need it:

# .npmrc
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=@types/*

Then reinstall:

rm -rf node_modules
pnpm install

Fix 2: Use shamefully-hoist (quick fix)

This makes pnpm behave like npm — flat node_modules:

# .npmrc
shamefully-hoist=true
rm -rf node_modules
pnpm install

This works but defeats pnpm’s strictness. Use it as a temporary fix while you figure out which packages actually need hoisting.

Fix 3: Add the missing dependency explicitly

The cleanest fix — if package A needs package B but doesn’t declare it, install B yourself:

# Check what's missing
pnpm why missing-package

# Install it explicitly
pnpm add missing-package

Fix 4: Use pnpm’s node-linker option

# .npmrc — use npm-style flat node_modules
node-linker=hoisted

This changes pnpm’s linking strategy entirely. Less strict than default, more strict than shamefully-hoist.

Fix 5: Report the bug upstream

If a package doesn’t declare its dependencies properly, it’s a bug in that package. Open an issue:

The package imports X but doesn't list it in dependencies or peerDependencies.
This breaks with pnpm's strict node_modules structure.

Many maintainers fix this quickly once reported.

How to prevent it

  • Start with strict mode (pnpm’s default) and only add hoisting for specific packages that need it
  • Use public-hoist-pattern instead of shamefully-hoist — it’s more targeted
  • When evaluating new packages, check if they work with pnpm before committing to them
  • Consider using pnpm vs npm to understand the tradeoffs