Webpack Module Not Found — Missing resolve Extension or Alias
Fix "Module not found" by adding the file extension to resolve.extensions, defining aliases, and resolving case-sensitive path mismatches.
Symptoms
- Module not found: Error: Can't resolve './Button' in /src
- Works locally but fails on a case-sensitive Linux build
- An absolute-looking import fails without an alias
Possible causes
- The import omits an extension that webpack does not resolve by default (for example .tsx)
- An alias such as @/ is used without a resolve.alias entry
- The path case differs from the file on a case-insensitive local filesystem
Diagnosis steps
Read the exact unresolved request
npx webpack --stats-error-details 2>&1 | grep -A 5 "Can't resolve"Interpretation
The error shows the issuer file and the request, revealing the missing extension or alias.
Check the resolve configuration
grep -n "extensions\|alias" webpack.config.js tsconfig.jsonInterpretation
Confirming configured extensions and aliases shows what to add.
Root cause
webpack resolves imports using resolve.extensions (default .js, .json, .wasm) plus aliases. An import without a resolvable extension or alias fails, and a case mismatch passes locally on case-insensitive filesystems but fails on Linux builders.
Fix
Add the needed extensions to resolve.extensions, define aliases for path shortcuts, and match file case exactly so builds are portable to case-sensitive filesystems.
Risk note
A very broad extensions list slows resolution; keep it ordered and minimal.
Verify the fix
Rebuild and confirm the module resolves; run the build in a case-sensitive environment to catch case mismatches.
Symptoms
When you hit “Webpack Module Not Found — Missing resolve Extension or Alias”, guessing wastes time. The guide below follows evidence: reproduce the symptom, run targeted diagnostics, identify the root cause, apply the fix, and verify it with concrete checks.
Observed symptoms include:
- Module not found: Error: Can’t resolve ‘./Button’ in /src
- Works locally but fails on a case-sensitive Linux build
- An absolute-looking import fails without an alias
Reproduce and Diagnose
Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.
Step 1: Read the exact unresolved request
npx webpack --stats-error-details 2>&1 | grep -A 5 "Can't resolve"
The error shows the issuer file and the request, revealing the missing extension or alias.
Step 2: Check the resolve configuration
grep -n "extensions\|alias" webpack.config.js tsconfig.json
Confirming configured extensions and aliases shows what to add.
Likely contributors, in order of frequency:
- The import omits an extension that webpack does not resolve by default (for example .tsx)
- An alias such as @/ is used without a resolve.alias entry
- The path case differs from the file on a case-insensitive local filesystem
Root Cause
webpack resolves imports using resolve.extensions (default .js, .json, .wasm) plus aliases. An import without a resolvable extension or alias fails, and a case mismatch passes locally on case-insensitive filesystems but fails on Linux builders.
The Fix
Add the needed extensions to resolve.extensions, define aliases for path shortcuts, and match file case exactly so builds are portable to case-sensitive filesystems.
Watch out: A very broad extensions list slows resolution; keep it ordered and minimal.
// webpack.config.js
module.exports = {
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
};
// now both resolve
import Button from '@/components/Button';
Verify and Prevent
Rebuild and confirm the module resolves; run the build in a case-sensitive environment to catch case mismatches.
Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.
This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.