Skip to content
Latchkey

Node.js "Cannot find module" After Install - Fix Missing Dependency

A runtime "Cannot find module" means Node’s resolver could not locate what your code required. In CI it usually means the dependency was never installed, or is a devDependency stripped from the build.

What this error means

A script or test crashes at startup with Error: Cannot find module '<name>' and a MODULE_NOT_FOUND code. It often works locally but fails in CI, which is the tell-tale sign of a missing or misclassified dependency.

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

Common causes

The package is used but not in package.json

Code requires a module that is only present locally (e.g. installed ad hoc) and was never added to dependencies, so a clean CI install never fetches it.

It is a devDependency in a production install

Something required at runtime sits under devDependencies. A npm ci --omit=dev (or NODE_ENV=production) install drops it, and the require fails.

Stale or partial node_modules

A cached node_modules from an older lockfile, or an install that was interrupted, can be missing the package even though package.json lists it.

How to fix it

Add the dependency and reinstall cleanly

Declare the package in the right section and regenerate the lockfile.

Terminal
npm install lodash        # or --save-dev if it is build-only
rm -rf node_modules
npm ci

Check the runtime vs dev split

  1. Confirm anything required at runtime is in dependencies, not devDependencies.
  2. If CI uses --omit=dev, verify the build does not need the omitted packages at runtime.
  3. Bust the node_modules cache if it predates the current lockfile.

How to prevent it

  • Run a clean npm ci in CI to catch undeclared deps early.
  • Keep runtime deps out of devDependencies.
  • Key node_modules cache on the lockfile hash.

Frequently asked questions

Why does it work locally but not in CI?
Locally you may have the package from an earlier ad hoc install or a different lockfile state. CI does a clean install from package.json/lockfile, so anything undeclared or misclassified is exposed.

Related guides

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