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)

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.

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 ""Can't resolve""?
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.
How do I fix "Can't resolve"?
Add the missing package and confirm the import resolves to a real file, with exact casing.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card