Skip to content
Latchkey

npm "Cannot find module" After --omit=dev - Build Tool Stripped in CI

A production install (--omit=dev or NODE_ENV=production) drops devDependencies. If your build step needs a tool that lives there - TypeScript, a bundler, a plugin - the build then fails to find it.

What this error means

Install succeeds, but the build step crashes with Cannot find module for a build tool (e.g. typescript, vite, a webpack loader). It works in a normal install but breaks once --omit=dev strips devDependencies.

npm output
$ npm ci --omit=dev
$ npm run build
> tsc -p tsconfig.json
sh: 1: tsc: not found
npm error code 127

Diagnose it: reproduce the CI install locally

Install failures are usually environment drift rather than a broken lockfile: a different package-manager major, a different Node version, or a cache that is being restored from a run with different inputs. Reproduce the CI conditions before changing the lockfile, because regenerating it hides the real cause.

Terminal
# match the runner exactly, then install from a clean slate
node --version && npm --version
rm -rf node_modules
npm ci --foreground-scripts

# if that succeeds locally but fails in CI, the difference is the cache
# or the package-manager version, not your lockfile

Common causes

Build tooling is in devDependencies but the build runs after a prod install

Compilers and bundlers are devDependencies by convention. A --omit=dev install removes them, so the build cannot run.

NODE_ENV=production implicitly omits dev deps

Setting NODE_ENV=production makes npm skip devDependencies even without --omit=dev, producing the same gap.

How to fix it

Install dev deps for the build, prune after

Do a full install to build, then prune to production for the runtime artifact.

Terminal
npm ci                 # includes devDependencies
npm run build
npm prune --omit=dev   # drop dev deps from the final image

Split build and runtime installs

  1. Run the build with a complete install (no --omit=dev).
  2. Produce the runtime image with npm ci --omit=dev over the built output.
  3. Do not set NODE_ENV=production for the build stage.

Verify the fix survives a cold cache

A green run immediately after a fix often proves nothing, because it restored a cache written before the change. Force a cold install once to confirm the fix is real.

.github/workflows/ci.yml
# temporarily bust the cache key to prove the fix on a cold runner
- uses: actions/setup-node@v4
  with:
    node-version: 22
    cache: npm
    cache-dependency-path: package-lock.json
# then bump this suffix once, run, and remove it
#   key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}-v2

How to prevent it

  • Build with all deps; prune to production afterward.
  • Use multi-stage Docker to separate build and runtime installs.
  • Avoid NODE_ENV=production during the build step.

Frequently asked questions

What causes npm "Cannot find module" after --omit=dev?
There are 2 common causes: build tooling is in devdependencies but the build runs after a prod install and node_env=production implicitly omits dev deps. Compilers and bundlers are devDependencies by convention.
How do I fix npm "Cannot find module" after --omit=dev?
There are 2 fixes depending on which cause you have: install dev deps for the build, prune after and split build and runtime installs. Work through them in order, since the first is the most common.
What does npm "Cannot find module" after --omit=dev actually mean?
Install succeeds, but the build step crashes with Cannot find module for a build tool (e.g.
How do I stop npm "Cannot find module" after --omit=dev happening again?
Build with all deps; prune to production afterward. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card