ERR_MODULE_NOT_FOUND is a Node.js error that fires when the ESM (ECMAScript Module) loader cannot resolve a module path or file extension you've imported.
What "ERR_MODULE_NOT_FOUND" Means
This error tells you Node's import statement failed to locate the file or package you referenced. Unlike CommonJS require(), ESM requires explicit file extensions and full paths — Node won't guess .js or index.js for you.
Why It Happens
The two most common causes are:
- Missing file extension — you wrote
import foo from './foo'instead of'./foo.js'. Node's ESM loader strictly enforces extensions. - Wrong package path — you imported from a package's internal file (e.g.,
import x from 'lodash/fp') but that subpath isn't exported in the package'spackage.jsonexportsfield.
Example Code That Triggers It
Create index.js and helper.js in the same folder:
// helper.js
export const greet = () => 'Hello from helper';
// index.js
import { greet } from './helper'; // ← missing .js extension
console.log(greet());
Run node index.js. You'll get:
node:internal/errors:477
Error [ERR_MODULE_NOT_FOUND]: Cannot find module './helper' imported from /path/to/index.js
How to Fix It
Add the .js extension to the import:
// index.js
import { greet } from './helper.js'; // ← fixed
console.log(greet());
The fix works because Node's ESM resolver now has an exact file path to check. It doesn't search for alternative extensions or index files — it treats './helper' as a literal path that doesn't exist.
Common Mistakes That Cause This
Mistake 1: Relying on bundler behavior. If you're used to Vite or webpack, they auto-resolve extensions. Node doesn't. Always write .js (or .mjs/.cjs) explicitly in ESM files.
Mistake 2: Mixing type: "module" with old paths. Setting "type": "module" in package.json flips all .js files to ESM. If you copy-paste CommonJS-style imports without extensions, every one of them breaks with this exact error.
When Should You Worry About This?
You should worry when the error appears in a production deployment, not just locally. If ERR_MODULE_NOT_FOUND shows up in your CI pipeline or Docker build, it usually means a dependency updated its exports map — breaking a subpath you imported directly. Check your package-lock.json for recent version bumps before debugging your own code.
Next time this error appears, check the import statement's file extension first — nine times out of ten, that's the entire problem.