Skip to content
Latchkey

pnpm "Cannot find module X" - Fix Phantom Dependencies & Hoisting in CI

pnpm’s node_modules is strict and non-flat: a package can only import what it actually declares. Code that relied on a transitive dependency being hoisted (a phantom dependency) breaks under pnpm with "Cannot find module".

What this error means

After switching to pnpm (or in CI using pnpm), a Cannot find module X appears for a package you never explicitly installed but which used to resolve. It worked under npm/yarn because flat hoisting happened to expose it.

Node output
Error: Cannot find module 'debug'
Require stack:
- /app/src/logger.js
    at Function._resolveFilename (node:internal/modules/cjs/loader)
    ... code: 'MODULE_NOT_FOUND'

Common causes

A phantom (undeclared) dependency

Your code imports a package that is only a transitive dependency. npm/yarn hoisting put it at the top of node_modules, so it resolved; pnpm’s strict layout does not, so it fails.

Relying on hoisting instead of declaring deps

The package was never added to package.json but happened to be reachable. pnpm exposes that gap by design.

How to fix it

Declare the dependency explicitly

Add every package you import to package.json so pnpm can resolve it.

Terminal
pnpm add debug        # declare what you actually import
pnpm install

Last-resort hoisting

  1. If you must unblock immediately, public-hoist-pattern / shamefully-hoist in .npmrc mimics flat layout.
  2. Treat that as a stopgap and add the real dependencies.
  3. Audit imports against package.json to find other phantoms.

How to prevent it

  • Declare every imported package in package.json.
  • Use pnpm locally too so phantoms surface before CI.
  • Avoid relying on hoisting/flattening to resolve imports.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →