Resolving 'Module Not Found' Errors in pnpm's Non-Flat node_modules
Learn how to diagnose and fix 'Module not found' errors caused by pnpm's non-flat node_modules structure and how to handle phantom dependencies.
17 Jul 2025, 00:10 UTC

The Problem: Missing Dependencies in a Valid Installation
You have run pnpm install, and your package.json contains all the necessary dependencies. However, your build tool, test runner, or runtime throws a Module not found error for a package that you know is present in your lockfile, but not explicitly listed in your package.json.
This happens because pnpm uses a non-flat node_modules structure. Unlike npm or Yarn v1, which "hoist" all transitive dependencies to the root of node_modules, pnpm creates a nested symlink structure. This prevents phantom dependencies—the ability for your code to import a package that it doesn't explicitly depend on, but which happens to be a dependency of one of your dependencies.
Diagnostic Matrix: Identifying the Cause
| Symptom | Likely Cause | Diagnostic Check |
|---|---|---|
Module not found for a transitive dependency |
Phantom Dependency | Check if the package is in package.json |
Tool fails to find a package that IS in package.json |
Symlink Resolution Failure | Check if the tool supports symlinks/junctions |
| Disk space not decreasing across multiple projects | Store Misconfiguration | Run pnpm store path |
Step-by-Step Resolution Path
1. Verify the Dependency Source
First, determine if you are attempting to use a phantom dependency. Run the following command in your project root to see where the package actually lives:
# Replace [package-name] with the missing module
pnpm list [package-name]
If the output shows the package is a dependency of another package but not listed under your project's root dependencies, you have a phantom dependency. The fix is to explicitly add it:
pnpm add [package-name]
2. Test for Symlink Incompatibility
Some legacy build tools or custom loaders do not follow symlinks (the pointers pnpm uses to link the .pnpm virtual store to your node_modules). To verify if the tool is the problem, check the node_modules folder. You should see a .pnpm directory containing the actual physical files and symlinks elsewhere.
If the tool fails despite the package being explicitly listed in package.json, you may need to force a flat structure for compatibility.
3. Implementing a Hoisting Workaround
If a third-party tool cannot resolve pnpm's symlink structure, you can use the shamefully-hoist setting. This emulates the flat node_modules behavior of npm.
- Create or edit a
.npmrcfile in your project root. - Add the following line:
shamefully-hoist=true - Run
pnpm installto rebuild thenode_modulesstructure.
Risk: This reintroduces phantom dependencies, meaning your code may rely on packages that aren't explicitly declared, potentially leading to crashes if a dependency updates its own internal tree.
Verification and Validation
To ensure the fix is working and understand the state of your installation, perform these checks:
- Verify Storage: Run
pnpm store path. This confirms the location of the content-addressable store. If this path is on a different drive than your project, pnpm may use hard links or copies depending on the OS (NTFS vs ext4), which can affect performance. - Verify Isolation: If you did NOT use
shamefully-hoist, try to import a known transitive dependency in a script. It should fail. This confirms your environment is protected from phantom dependencies. - Verify Structure: Run
ls -la node_modules(Linux/macOS) ordir node_modules(Windows). You should see entries marked as symlinks (or junctions on Windows) pointing to the.pnpmfolder.
When to Escalate
If the following conditions persist, move beyond configuration changes to environment debugging:
- The
Module not founderror persists aftershamefully-hoist=trueand a freshpnpm install. - The
pnpm store pathreturns a directory that is inaccessible due to permission errors (requires administrative/sudo privileges to write). - You are using a Docker container where the global store is on a different volume than the project, causing hard-link failures.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.