Error: Cannot find module 'X' with a printed require stack is Node's CommonJS module resolution failing to locate a module — and the require stack it prints alongside the error is genuinely useful, showing you the exact chain of require() calls that led to the failed resolution, which is often more informative than the missing module name alone.
This error means Node's module resolution algorithm searched all the expected locations (relative paths, then progressively up through node_modules directories) for the specified module and found nothing — the require stack shows which file did the requiring, which matters because the actual bug is sometimes in a different file than where the error surfaces.
Why This Error Happens
Node resolves require('module-name') calls in a specific order: first checking if it's a core Node module, then a relative/absolute path if the specifier starts with ./ or /, then searching up the directory tree through node_modules folders. This error means none of those resolution steps found a match — commonly because a dependency was never installed, was installed but not saved to package.json (so it's missing after a clean install), a relative path has a typo, or the module exists but under a different name/casing than requested.
Reproducing and Diagnosing the Error
Reading the require stack to find the actual source of the problem:
Error: Cannot find module 'lodash.debounce'
Require stack:
- /app/src/utils/search.js
- /app/src/components/SearchBox.js
- /app/src/index.js
The require stack reads bottom-up as the call chain: index.js required SearchBox.js, which required search.js, which is the file actually attempting the failed require('lodash.debounce') — this tells you exactly which file to open and fix, rather than searching your whole codebase for the string.
Core Concepts Behind This Error
The require stack shows the chain of files that led to the failing require, not necessarily the file with the bug — the last entry (or the error's originating file, depending on your Node version's exact formatting) is where the actual missing require() call lives; the rest of the stack is context showing how execution got there.
A dependency present in package.json but missing from node_modules is the most common cause after cloning a repo or pulling changes — someone added a dependency to package.json (or it was added via a lockfile merge) without you running an install afterward, so the code references something that isn't actually installed in your local node_modules.
Case sensitivity differences between operating systems can cause this error inconsistently across environments — a module or file path that resolves correctly on a case-insensitive filesystem (macOS, Windows) can fail with MODULE_NOT_FOUND on a case-sensitive one (Linux, most CI systems) if the actual casing doesn't match exactly.
Monorepo and workspace setups add another resolution layer — a package expected to resolve via a workspace symlink can fail to be found if the workspace wasn't properly linked (a missing pnpm install or npm install at the workspace root after adding a new internal package dependency).
Fixing "MODULE_NOT_FOUND"
Fix 1: Run your package manager's install command to ensure node_modules matches package.json/lockfile, the most common and simplest fix:
pnpm install
# or: npm install / yarn install
Fix 2: For relative import path errors, verify the exact path and casing match the actual file on disk, especially when the code works locally but fails in CI (a strong signal of a case-sensitivity mismatch):
// Wrong: casing mismatch, works on macOS/Windows, fails on Linux CI
import { Button } from "./components/button";
// Fixed: matches actual file casing exactly
import { Button } from "./components/Button";
Fix 3: For monorepo/workspace setups, ensure the workspace is properly linked after adding a new internal package dependency:
pnpm install # re-links workspace packages after package.json changes
# verify: ls node_modules/@yourscope/internal-package should show a symlink
Fix 4: If the module was genuinely never installed, add it explicitly rather than assuming it should already be present:
pnpm add lodash.debounce
Why Does This Error Sometimes Only Happen in CI, Not Locally?
Usually one of two reasons: case sensitivity (CI runners are typically Linux, which is case-sensitive, while local development on macOS or Windows tolerates mismatched casing), or a dependency that's present in your local node_modules (perhaps installed manually or leftover from an earlier state) but never properly recorded in package.json/the lockfile, so a clean CI install never installs it. Both point to the same underlying fix: don't rely on local node_modules state — verify what's actually declared and committed.
Preventing This Error in Production
Run installs from a clean state periodically (or in CI, always) to catch drift between your local node_modules and what's actually declared in package.json and the lockfile, rather than relying on an accumulated local state that might mask missing dependencies. Match import path casing exactly to actual file casing on disk, and test in a case-sensitive environment (or via CI) even if your primary development machine is case-insensitive.
If you hit this error, read the require stack first to identify exactly which file has the failing require() — it saves significant time over guessing, especially in larger codebases with deep import chains.