The require function is trying to load a module that was exported using export default, and it doesn’t know how to handle that.
This happens because Node.js has two module systems: CommonJS (CJS), which uses require() and module.exports, and ECMAScript Modules (ESM), which uses import and export. When you try to require() an ESM module, Node.js gets confused because the default export mechanism in ESM doesn’t directly map to how CJS expects to find exports.
Here are the common reasons this error pops up and how to fix them:
-
Trying to
require()an ESM module directly:- Diagnosis: You’ll see the error message when your CJS file attempts to
require()a file that usesexport defaultor top-levelexport. - Fix: If the module you’re importing is intended to be used in a CJS context, you need to ensure it’s also exported in a CJS-compatible way. This usually means the module author needs to provide a CJS build or you need to configure your build process (like Webpack or Rollup) to generate CJS output. If you control the module you’re importing, change its exports:
If you must// Original ESM export // export default { someValue: 123 }; // CJS compatible export module.exports = { someValue: 123 };requirean ESM module, and it has adefaultexport, you can often access it via a.defaultproperty:// In your CJS file const esmModule = require('your-esm-module'); const value = esmModule.default; // Access the default export - Why it works: CJS expects exports to be properties of the
module.exportsobject. When an ESM module usesexport default, that default export is often attached to theexportsobject under the keydefault. Accessing it directly resolves the conflict.
- Diagnosis: You’ll see the error message when your CJS file attempts to
-
Incorrect
type: "module"inpackage.json:- Diagnosis: Your
package.jsonhas"type": "module", which tells Node.js to treat all.jsfiles as ESM by default. However, you might still have some files that are written in CJS syntax and are being incorrectly interpreted as ESM. - Fix: If you want your project to be primarily ESM, but have specific CJS files, rename those CJS files to have a
.cjsextension. Node.js will then correctly interpret them as CommonJS.// package.json { "type": "module", // ... }# Rename your CJS file mv my-cjs-file.js my-cjs-file.cjs - Why it works: Explicitly naming files with
.cjsoverrides the globaltype: "module"setting for those specific files, ensuring they are parsed as CommonJS.
- Diagnosis: Your
-
Mixing
importandrequirewithin the same file (and Node.js version issues):- Diagnosis: You’re using both
importandrequirestatements in a single file, and Node.js is getting confused about which module system it’s operating in. This is particularly problematic in older Node.js versions. - Fix: Avoid mixing
importandrequirein the same file. If you need to import CJS modules from an ESM file, use dynamicimport():
If you need to use ESM features in a CJS file, you generally can’t directly. You’d typically refactor the file to be ESM (by setting// In your ESM file (e.g., with "type": "module") async function loadCjsModule() { const cjsModule = await import('your-cjs-module'); // Use cjsModule.someExport } loadCjsModule();"type": "module"and using.jsextensions, or using.mjsextensions) or use the.defaultaccess method if the ESM module is structured that way. - Why it works: Dynamic
import()is the officially supported way to load CommonJS modules from an ECMAScript Module context. It handles the interop layer correctly.
- Diagnosis: You’re using both
-
Third-party library not supporting ESM correctly:
- Diagnosis: You’re trying to
importa library that is published as ESM, but it’s not correctly exporting its modules or has internal CJS dependencies that aren’t handled well. - Fix: Check the library’s documentation for ESM support. It might require a specific import syntax, or it might have a separate CJS build you need to use. If the library is known to have issues, you might need to use a compatibility layer or find an alternative. For example, some libraries might export their main module under
your-lib/dist/index.mjsor similar.// Potentially import { someFunction } from 'your-broken-esm-lib/dist/index.mjs'; - Why it works: Explicitly pointing to the correct ESM entry point of the library, or using a version/build that is designed for ESM, bypasses the internal conflicts.
- Diagnosis: You’re trying to
-
Transpilation issues with Babel or TypeScript:
- Diagnosis: Your build tool (like Babel or
tsc) is configured to output CJS, but it’s encountering ESM syntax it can’t correctly transform, or vice-versa. - Fix: Ensure your
tsconfig.json(for TypeScript) or.babelrc/babel.config.js(for Babel) is correctly configured for the target module system.- TypeScript: Set
"module": "ESNext"(or similar ESM target) and"moduleResolution": "NodeNext"(or"Node16") if you’re building an ESM project. If you’re building CJS, use"module": "CommonJS"and"moduleResolution": "Node".
// tsconfig.json for ESM output { "compilerOptions": { "target": "ESNext", "module": "ESNext", "moduleResolution": "NodeNext", // ... other options } }- Babel: Use presets like
@babel/preset-envwith appropriatemodulesoption.
// .babelrc for ESM output { "presets": [ ["@babel/preset-env", { "modules": "esm" }] ] } - TypeScript: Set
- Why it works: Correct transpiler configuration ensures that the input module syntax is accurately converted to the desired output module format, resolving any internal inconsistencies.
- Diagnosis: Your build tool (like Babel or
After fixing these, you might encounter a "Cannot find module" error if your import paths are incorrect, especially when dealing with relative imports in ESM.