What this usually means
Node.js supports two module systems: CommonJS (CJS, using `require()` and `module.exports`) and ECMAScript Modules (ESM, using `import` and `export`). Node determines which system a file uses by: the `type` field in the nearest `package.json` (`type: 'module'` makes `.js` files ESM), the file extension (`.mjs` is always ESM, `.cjs` is always CJS), or the package's own module format. Problems happen when you use `import` in a CJS context, `require()` in an ESM context, or when a dependency ships code for one system but your project expects the other.
The first ten minutes \u2014 establish facts before touching code.
- 1Check the nearest `package.json` `type` field. If `type: 'module'`, `.js` files are ESM and cannot use `require()`. If no type or `type: 'commonjs'`, `.js` files are CJS and cannot use top-level `import`.
- 2Check the file extension. `.mjs` is always ESM. `.cjs` is always CJS. `.js` depends on `package.json`.
- 3Check if you are mixing `import` and `require()` in the same file. ESM files can use `import()` (dynamic import) but not `require()`.
- 4Check the dependency's module format. Some packages ship both ESM and CJS. Your bundler or runtime picks one based on the `exports` field in the package's `package.json`.
- 5Check if the error happens only when running directly with Node.js (not through a bundler). Bundlers can handle mixed module formats that Node.js cannot.
The specific files, logs, configs, and dashboards that usually own this bug.
- search`package.json` — `type` field, `exports` field, `main` and `module` fields
- searchThe failing file — its extension and import/require statements
- searchThe imported package's `package.json` — `type`, `exports`, `main`, `module`
- searchNode.js version — ESM support matured between Node 12 and Node 20
- searchBundler or transpiler config — Webpack, Vite, tsup, esbuild settings
- searchBuild output — compiled `.js` files may have different module format than source
Practical causes, not theory. These are the things you will actually find.
- warning`type: 'module'` in package.json but using `require()` in `.js` files
- warningNo `type` field and using `import` in `.js` files (Node treats them as CJS)
- warningImporting a CJS package that uses `module.exports` with a named ESM import `import { foo }` — CJS exports might not be statically analysable
- warningA dependency ships only ESM but your project is CJS (or vice versa)
- warningTypeScript `compilerOptions.module` does not match the runtime module system
- warningPackage `exports` field restricts which files can be imported and how
Concrete fix directions. Pick the one that matches your root cause.
- buildRename file to `.mjs` (for ESM) or `.cjs` (for CJS) to override the package.json type
- buildSet `type: 'module'` or `type: 'commonjs'` explicitly in package.json — do not rely on default
- buildUse `import()` (dynamic import) to load CJS modules from ESM files
- buildUse `createRequire` from `module` to use `require()` inside an ESM file: `import { createRequire } from 'module'; const require = createRequire(import.meta.url);`
- buildFor CJS packages imported in ESM, use default import: `import pkg from 'cjs-package'` then destructure
- buildCheck the package's documentation for the recommended import syntax for each module system
A fix you cannot prove is a guess. Close the loop.
- verifiedRun the file with `node <file>` directly. It should work without a bundler.
- verifiedTest both `import` and `require()` paths if the module supports both.
- verifiedRun in CI on the same Node.js version as production.
- verifiedCheck the build output — the compiled file should use the module system the runtime expects.
- verifiedWrite a simple test that imports the problematic module and verifies it works.
Things that make this bug worse or harder to find.
- warningMixing `import` and `require()` in the same file without understanding the module context
- warningAssuming all packages support both ESM and CJS — many ship only one
- warningNot setting `type` in package.json and relying on default behaviour
- warningUsing a bundler for development but running unbundled in production (or vice versa)
- warningRenaming `.js` to `.mjs` without updating all imports that reference the file