Skip to content
Latchkey

Webpack "Module not found: Can't resolve" - Fix in CI

Webpack walked an import/require and could not find the target on disk or in node_modules. The cause is almost always a dependency that was never installed, a path that is wrong, or a resolve config the build never set up.

What this error means

The build fails with Module not found: Error: Can't resolve '<module>' pointing at the importing file. It is deterministic - the same import fails the same way every run, and re-running never helps.

webpack output
ERROR in ./src/App.jsx 3:0-29
Module not found: Error: Can't resolve './componets/Header' in '/app/src'
resolve './componets/Header' in '/app/src'
  using description file: /app/package.json (relative path: ./src)

Diagnose it: is it resolution, transform, or memory?

Bundler failures in CI fall into three families and the error text often points at the wrong one. A module that resolves on your machine and not on the runner is nearly always case sensitivity or a missing optional dependency; a transform error is a config or version mismatch; and an unexplained kill with no stack is the out-of-memory reaper, not a build error at all.

Terminal
# 1. resolution: does the file exist with EXACTLY that case?
git ls-files | grep -i "the/imported/path"

# 2. transform: what versions is CI actually resolving?
npm ls webpack vite rollup esbuild typescript 2>/dev/null | head -20

# 3. memory: was it killed rather than failed?
#    exit 137 = SIGKILL (OOM). Nothing in the bundler log will explain it.
node --max-old-space-size=4096 node_modules/.bin/vite build

Common causes

Dependency not installed

The package is imported but missing from node_modules - not in package.json, or npm ci ran against a lockfile that does not include it. Works locally where it was installed ad hoc.

Wrong path or case mismatch

A typo (./componets), a wrong relative depth, or a casing difference. The last bites hardest in CI: Linux is case-sensitive, so ./Header vs ./header passes on macOS and fails on the runner.

Missing resolve alias or extension

An alias like @/ or a non-default extension (.ts, .jsx) is not declared in resolve.alias / resolve.extensions, so Webpack cannot map the bare specifier to a file.

How to fix it

Install the dependency and verify the path

Add the missing package and confirm the import resolves to a real file, with exact casing.

Terminal
npm install <package>
# verify the file exists with that exact case
ls -la src/components/Header.jsx

Declare aliases and extensions

Make custom specifiers resolvable in the Webpack config.

webpack.config.js
// webpack.config.js
resolve: {
  alias: { '@': path.resolve(__dirname, 'src') },
  extensions: ['.js', '.jsx', '.ts', '.tsx'],
}

Match casing for case-sensitive runners

  1. Compare the import string against the real filename, character for character.
  2. Rename the file or the import so casing matches exactly.
  3. Add CaseSensitivePathsPlugin so the mismatch fails locally too, not only in CI.

Make the build reproducible before you debug it

  • Pin the Node major in setup-node and in engines. A bundler that resolves native bindings will pick a different prebuilt binary across majors.
  • Delete node_modules locally and reinstall from the lockfile before concluding the runner is at fault; most "works locally" reports are stale local state.
  • Set CI=true locally to reproduce. Several toolchains change behaviour under it, including treating warnings as errors.
  • Exit code 137 is an out-of-memory kill. Raise --max-old-space-size or move to a larger runner rather than searching the bundler config.

How to prevent it

  • Commit a lockfile and install with npm ci so dependencies are reproducible.
  • Use CaseSensitivePathsPlugin so case bugs surface on macOS/Windows before CI.
  • Keep Webpack resolve.alias in sync with your tsconfig paths.

Frequently asked questions

What causes Webpack "Module not found: Can't resolve"?
There are 3 common causes: dependency not installed, wrong path or case mismatch, and missing resolve alias or extension. The package is imported but missing from node_modules - not in package.json, or npm ci ran against a lockfile that does not include it.
How do I fix Webpack "Module not found: Can't resolve"?
There are 3 fixes depending on which cause you have: install the dependency and verify the path, declare aliases and extensions, and match casing for case-sensitive runners. Work through them in order, since the first is the most common.
What does Webpack "Module not found: Can't resolve" actually mean?
The build fails with Module not found: Error: Can't resolve '<module>' pointing at the importing file.
How do I stop Webpack "Module not found: Can't resolve" happening again?
Commit a lockfile and install with npm ci so dependencies are reproducible. 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