Diagnosing 'Module Not Found' Errors in pnpm's Strict Dependency Tree
Learn how to diagnose and fix 'Module Not Found' errors in pnpm caused by strict dependency resolution and phantom dependencies, including when to use shamefully-hoist.
16 Feb 2026, 20:46 UTC

The Problem: Phantom Dependencies
When migrating a project from npm or Yarn to pnpm, you may encounter Error: Cannot find module 'package-name' during runtime or build time, even though the package exists physically on your disk. This happens because pnpm uses a non-flat node_modules structure to prevent "phantom dependencies"—packages that are used in code but are not explicitly listed in your package.json.
Unlike npm, which flattens dependencies into the root node_modules, pnpm uses a content-addressable store and symlinks. Only the packages you explicitly define as dependencies are visible to your application. If a package you are importing is actually a dependency of one of your dependencies, pnpm hides it from your code to ensure dependency integrity.
Diagnostic Matrix
| Symptom | Likely Cause | Verification Method |
|---|---|---|
| Module not found in pnpm, but works in npm/Yarn | Phantom Dependency | Check if package is missing from package.json |
| Module not found only in CI/CD environments | Store Path/Permission Issue | Check store-dir in .npmrc |
| Peer dependency warnings during install | Missing Peer Dependency | Run pnpm install and check stderr |
Step-by-Step Resolution Path
1. Verify the Dependency Source
First, determine if the missing module is a direct requirement of your project or a transitive dependency (a dependency of a dependency). Run the following command in your project root:
pnpm list <package-name>
Expected Result: If the package is listed but not under your project's direct dependencies, it is a transitive dependency. If it is not listed at all, it is missing from the lockfile.
2. Fix via Explicit Installation (Recommended)
The most stable fix is to make the dependency explicit. This ensures your project is portable and not relying on the internal structure of another library.
Run this command with administrative/write permissions for the project directory:
pnpm add <package-name>
Risk: This adds a new entry to your package.json. Ensure you are installing the version compatible with the library that originally brought it in.
3. Fix via Public Hoisting (The "Escape Hatch")
If you are dealing with a large legacy codebase or a tool that expects a flat node_modules structure (common with some older build tools), you can force pnpm to hoist dependencies. This mimics npm's behavior.
Create or edit the .npmrc file in your project root and add the following line:
shamefully-hoist=true
After saving the file, you must re-install dependencies for the changes to take effect:
pnpm install
Warning: This disables pnpm's primary safety mechanism. It allows your code to import any package in the dependency graph, which can lead to "it works on my machine" bugs when dependencies update their own internal requirements.
Verifying the Fix
To confirm the resolution, perform these checks:
- For Explicit Installation: Verify the package appears in the
dependenciessection ofpackage.json. - For Hoisting: Check the root
node_modulesfolder. Ifshamefully-hoist=trueis working, the missing package will now appear as a physical folder/symlink in the root, rather than being hidden insidenode_modules/.pnpm. - Runtime Check: Execute your build or start command (e.g.,
pnpm run build) to ensure theModule not founderror is resolved.
Rollback Procedure
If hoisting causes version conflicts or unexpected behavior, revert the state as follows:
- Remove
shamefully-hoist=truefrom.npmrc. - Delete the
node_modulesfolder:rm -rf node_modules(Unix) orrmdir /s /q node_modules(Windows). - Run
pnpm installto restore the strict symlink structure.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.