# Node.js ERR_REQUIRE_ESM: require() of an ES Module is not supported
A CommonJS file tried to require() an ES module. Since Node 22.12 this is allowed for modules that are fully synchronous, so on a current runtime the error usually means the module contains top-level await — a different failure that most advice about this error predates.
| Error | Error [ERR_REQUIRE_ESM]: require() of ES Module not supported |
|---|---|
| Applies to | Node.js 12 and later · CommonJS all versions |
| Primary cause | The Node version predates require(esm) support |
| First check | node --version && node -e "try{require('the-package')}catch(e){console.log(e.code)}" |
| Confidence | medium2 sources, 2 primary |
| Verified | 2026-08-08fresh0d old · recheck by 2027-02-04 |
| Domain | languagenodejs esm commonjs modules packaging interop |
## Error
Error [ERR_REQUIRE_ESM]: require() of ES Module not supportedCodes: ERR_REQUIRE_ESMERR_REQUIRE_ASYNC_MODULE
Also seen as: require() of ES modules is not supported · Must use import to load ES Module · ERR_REQUIRE_ASYNC_MODULE · Cannot use import statement outside a module
## Problem
A dependency that worked before now throws on require(), usually after upgrading it to a major version that shipped as ESM-only. The application is CommonJS, the library is not, and the two cannot be mixed by the old rules. Advice found online contradicts itself because the rules changed: what was impossible before Node 22.12 is now permitted for a subset of modules.
## Root Cause5 known causes, ranked
- 01
The Node version predates require(esm) support
primaryBefore Node 22.12 a CommonJS file could not require() an ES module under any circumstances. On those runtimes the error is unconditional and no change to the dependency will fix it.
→ how to tell: node --version reports below 22.12, and the error code is ERR_REQUIRE_ESM
- 02
The module is not fully synchronous
primaryCurrent Node allows require() of an ES module only if it has no top-level await. An asynchronous module cannot be evaluated synchronously, so the error persists on a new runtime — but with a different code.
→ how to tell: Node is 22.12 or newer and the code is ERR_REQUIRE_ASYNC_MODULE, or the module source contains await outside any function
- 03
The importing file is being treated as CommonJS unintentionally
commonA .js file is CommonJS unless the nearest parent package.json declares "type": "module". Adding an import statement to such a file produces a syntax error rather than an ESM file.
→ how to tell: The nearest package.json has no type field or says commonjs, while the file uses import syntax
- 04
The dependency published only an ESM entry point
commonA library that dropped its CommonJS build has no export the require() condition can resolve. Its major-version notes usually say ESM-only, which is the real change rather than a bug.
→ how to tell: The package's exports field offers only an import condition, with no require condition or main
- 05
A transpiler emits require() for what is genuinely ESM
edgeTypeScript or Babel configured to output CommonJS turns import statements into require() calls, so source that looks like ESM runs as CJS and hits the same wall at runtime.
→ how to tell: The source uses import but the compiled output in dist contains require(), and module in tsconfig is commonjs
## Solution
- 01Establish which of the two errors you have, because the fixes differ. Check the runtime version and the exact error code before changing anything.
$ node --version && node -e "try{require('the-package')}catch(e){console.log(e.code)}" - 02On Node older than 22.12, upgrade the runtime if you can. This alone resolves the common case of requiring a synchronous ESM-only library.
$ node --version # target 22.12+ or 24 LTS - 03Where the runtime cannot change, load the module asynchronously. Dynamic import works from CommonJS on every supported version and returns a promise.javascript
// 🔴 fails when the-package is ESM-only on an older runtime const pkg = require("the-package"); // ✅ works from CommonJS everywhere async function main() { const { default: pkg } = await import("the-package"); return pkg(); } // for a value needed at module scope, keep it lazy let cached; const getPkg = async () => (cached ??= (await import("the-package")).default);note: The import() call is asynchronous and cannot be made synchronous. If the calling API must stay synchronous, the caller has to change too.
- 04If the error is ERR_REQUIRE_ASYNC_MODULE, the module has top-level await and no runtime will require() it. Use dynamic import, or if it is your own module, move the awaited work into an exported async function.javascript
// 🔴 top-level await makes this module unrequireable const config = await loadConfig(); export { config }; // ✅ defer the await to the caller export const getConfig = async () => loadConfig(); - 05To convert the importing project to ESM instead, declare it and fix the consequences — __dirname, require and .json imports all change.json
{ "type": "module" }note: Under type module, .js files are ESM and CommonJS-only files must be renamed to .cjs. This is a project-wide change, not a per-file one.
- 06If you publish the library, ship both entry points so consumers of either module system resolve correctly.json
{ "exports": { ".": { "require": "./dist/index.cjs", "import": "./dist/index.mjs" } } }
verify · The application starts and the module loads without an ERR_REQUIRE_ESM or ERR_REQUIRE_ASYNC_MODULE code, on the same Node version used in production rather than a newer local one.
if that fails · Where an ESM-only dependency cannot be loaded asynchronously and the runtime cannot move, pin the last version that shipped a CommonJS build and treat the upgrade as scheduled work — an ESM-only major release is a deliberate break, not a defect.
## Applies To
- Node.js
- 12 and later— require() of a synchronous ES module became supported in 22.12; before that it always failed. Asynchronous modules still cannot be required on any version.
- CommonJS
- all versions— A .js file is CommonJS unless the nearest package.json sets type to module.
- Runtimes
- Node.js
## Not Applicable Tonear misses this page does not answer
- ✗ Cannot use import statement outside a module, which is a parse error in a CJS file rather than a load failure
- ✗ ERR_MODULE_NOT_FOUND, where the specifier does not resolve at all
- ✗ Bundled applications where the bundler resolves modules at build time and Node never sees the require
- ✗ Browser module errors, which have no CommonJS to interoperate with
## Evidence2 sources
https://nodejs.org/api/modules.html
OpenJS Foundation · read 2026-08-08
supports: That require() supports ES modules only when they are fully synchronous — no top-level await — which is precisely why the error survives a runtime upgrade for asynchronous modules and disappears for synchronous ones.
“require() only supports loading ECMAScript modules that meet the following requirements: ... The module is fully synchronous (contains no top-level await)”
https://nodejs.org/api/packages.html
OpenJS Foundation · read 2026-08-08
supports: That the module system of a .js file is decided by the nearest parent package.json's type field, which determines whether an import statement is valid in it and whether its requires are CommonJS.
“Files with a .js extension when the nearest parent package.json file contains a top-level "type" field with a value of "module"”
## Confidence
mediumThe synchronous-module requirement and the type-field resolution rule are quoted from Node's own API documentation, and together they explain both error codes. Confidence is medium rather than high because it rests on two sources: the version at which require(esm) became available and the dual-export remedy are drawn from release history and ecosystem convention rather than from a sentence I could quote here.