Angular "Module not found: Error: Can't resolve" in CI
By Kaveh Alemi·Latchkey
The Angular build (webpack/esbuild under @angular-devkit/build-angular) could not resolve an import specifier. The path is wrong, the package is not installed, or a case-sensitive path differs between your machine and the Linux runner.
What this error means
ng build fails with "Module not found: Error: Can't resolve './foo' in '/home/runner/work/app/app/src/app'" pointing at a specific import.
ng build
./src/app/app.component.ts:5:0-42
Module not found: Error: Can't resolve './services/user.service' in '/home/runner/work/app/app/src/app'
Diagnose it: what is different about the runner?
A build that passes locally and fails on a runner differs in a small number of predictable ways. Check those before changing build configuration, because the build config is usually not the thing that changed.
macOS and Windows treat file names case-insensitively; the Linux runner does not, so User.service vs user.service fails only in CI.
A missing dependency or a wrong relative path
The imported package is not in the lockfile, or a relative path was renamed/moved without updating the import.
How to fix it
Match the import to the real file name and case
Compare the import string against the actual file name, including case.
Rename the import or the file so they match exactly.
For a package import, confirm it is installed with npm ls <pkg>.
app.component.ts
// file is user.service.ts
import { UserService } from './services/user.service';
Verify path aliases resolve in the build
If you use tsconfig paths, ensure the alias maps to a real directory that exists after install on the runner.
tsconfig.json
"paths": {
"@app/*": ["src/app/*"]
}
The three that account for most of them
Case sensitivity. Linux runners are case sensitive, macOS is not. An import with the wrong case resolves locally and fails in CI.
Out of memory. Exit code 137 is a SIGKILL from the kernel, not a build error. Raise --max-old-space-size or use a larger runner.
devDependencies pruned.NODE_ENV=production makes npm ci skip devDependencies, so the build tool itself goes missing. Set it after install, not before.
How to prevent it
Keep import paths case-exact so Linux runners match your machine.
Install all imported packages and commit the lockfile.
Validate tsconfig path aliases against real directories.
Frequently asked questions
What causes Angular "Module not found: Error: Can't resolve" in CI?
There are 2 common causes: case-sensitive path mismatch on linux and a missing dependency or a wrong relative path. macOS and Windows treat file names case-insensitively; the Linux runner does not, so User.service vs user.service fails only in CI.
How do I fix Angular "Module not found: Error: Can't resolve" in CI?
There are 2 fixes depending on which cause you have: match the import to the real file name and case and verify path aliases resolve in the build. Work through them in order, since the first is the most common.
What does Angular "Module not found: Error: Can't resolve" in CI actually mean?
ng build fails with "Module not found: Error: Can't resolve './foo' in '/home/runner/work/app/app/src/app'" pointing at a specific import.
How do I stop Angular "Module not found: Error: Can't resolve" in CI happening again?
Keep import paths case-exact so Linux runners match your machine. The prevention section lists 3 changes that keep it from recurring.