Skip to content
Latchkey

pnpm "Cannot find module" Without shamefully-hoist - Fix Non-Hoisted Deps in CI

pnpm builds a strict, non-flat node_modules where a package can only require what it declares. Code or tooling that relied on npm’s flat layout to reach an undeclared (but hoisted) dependency fails under pnpm with "Cannot find module".

What this error means

Switching to pnpm, a build/test fails with Cannot find module for a package that "was always there" under npm. The module is a transitive dependency that npm hoisted to the top level but pnpm keeps non-accessible because your package never declared it.

Node output
Error: Cannot find module 'lodash'
Require stack:
- /app/src/index.js
# lodash was a hoisted transitive under npm; pnpm does not expose it
# because the project never declared it as a direct dependency

Common causes

Relying on an undeclared, hoisted dependency

npm’s flat node_modules let code require packages it never declared (they happened to be hoisted). pnpm’s strict layout exposes only declared deps, so the require fails.

Tooling that expects a flat node_modules

Some tools assume a flat layout. Under pnpm’s symlinked store they cannot find modules unless hoisting is relaxed.

How to fix it

Declare the dependency (preferred)

Add the package you actually use to your own dependencies so pnpm exposes it correctly.

Terminal
pnpm add lodash      # declare what you import
pnpm install

Relax hoisting only if you must

For tooling that genuinely needs a flat layout, enable hoisting in .npmrc.

.npmrc
# .npmrc (pnpm)
shamefully-hoist=true
# or hoist a specific pattern:
public-hoist-pattern[]=*eslint*

How to prevent it

  • Declare every dependency you import; do not rely on hoisting.
  • Scope hoisting with public-hoist-pattern when a tool needs it.
  • Avoid blanket shamefully-hoist except as a last resort.

Related guides

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