error nodejs

Node.js ERR_MODULE_NOT_FOUND

Understanding Node.js ERR_MODULE_NOT_FOUND - the specified ES module could not be found or resolved by the module loader.

What It Means

ERR_MODULE_NOT_FOUND is thrown when Node.js cannot find the module specified in an import statement (ES modules). Unlike CommonJS require() which throws a generic MODULE_NOT_FOUND error, this error is specific to the ES module system and has stricter resolution rules.

Common Causes

  • Package not installed (npm install needed)
  • Missing file extension in import path (required for ES modules)
  • Incorrect relative path
  • Package doesn’t export the specified subpath
  • "type": "module" in package.json but using CommonJS conventions
  • TypeScript path aliases not resolved at runtime
  • Importing a CJS module from an ESM context incorrectly

How to Fix

Add file extensions to relative imports

// ES modules REQUIRE file extensions for relative imports

// Bad: no extension (works in CommonJS, fails in ESM)
import { helper } from './utils';

// Good: include the file extension
import { helper } from './utils.js';
import config from './config.json' with { type: 'json' };

Install missing packages

# Install the package
npm install express

# If using a monorepo, make sure you're in the right directory
cd packages/my-app && npm install

# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm install

Fix package.json “type” field

{
  "type": "module",
  "scripts": {
    "start": "node app.js"
  }
}
// With "type": "module", all .js files are ESM
// Use .cjs extension for CommonJS files in an ESM project
// Use .mjs extension for ESM files in a CJS project

Fix package exports/subpath

// Error: ERR_PACKAGE_PATH_NOT_EXPORTED
// The package doesn't export this subpath

// Bad: accessing internal files directly
import something from 'package/lib/internal.js';

// Good: use the package's public API
import { something } from 'package';

// Check what the package exports
// Look at the "exports" field in node_modules/package/package.json

Fix TypeScript path aliases

// TypeScript aliases like @/utils won't work at runtime without a resolver

// tsconfig.json
{
  "compilerOptions": {
    "paths": { "@/*": ["./src/*"] }
  }
}

// For runtime resolution, use one of:
// 1. tsx: npx tsx app.ts
// 2. tsconfig-paths: node -r tsconfig-paths/register dist/app.js
// 3. tsc-alias: tsc && tsc-alias

Fix CommonJS in ESM context

// Importing CommonJS modules in ESM
// Default import works for most CJS modules
import express from 'express';

// Named imports might not work directly
// Bad:
import { readFile } from 'fs';  // This works because fs is special

// For third-party CJS packages without named exports:
import pkg from 'some-cjs-package';
const { namedExport } = pkg;

// Or use createRequire
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const cjsModule = require('some-cjs-package');

Debug module resolution

# See how Node.js resolves modules
node --experimental-loader ./custom-loader.mjs app.js

# Check Node.js version (ESM support varies)
node --version

# Run with verbose module logging
NODE_DEBUG=module node app.js