Skip to content
Nilay Kabariya

Entry No.005·Fixes·Updated ·3 min read

Fix: ERR_REQUIRE_ESM require() of ES Module not supported

require() of an ES module: which Node versions throw ERR_REQUIRE_ESM (tested 20 to 26), the .default trap after upgrading, top-level await, and fixes.

by Nilay#node#esm#commonjsFIXED

The error, verbatim

Jump to the fix ↓
Error [ERR_REQUIRE_ESM]: require() of ES Module ...\node_modules\chalk\source\index.js
from ...\app.js not supported.
Instead change the require of index.js in ...\app.js to a dynamic import()
which is available in all CommonJS modules.
code: 'ERR_REQUIRE_ESM'
✓ Reproduced on Ubuntu on GitHub Actions; Windows 11 Pro

Tested on

Node
20.20.2, 22.11.0, 22.12.0, 24.22.1, 26.13.0 (Linux); 24.14.0, 26.11.1 (Windows)
Package
chalk 5.6.2 (ESM-only)
TypeScript
6.0, compiled to CommonJS
OS
Ubuntu on GitHub Actions; Windows 11 Pro

✓ Last re-run on GitHub Actions · see the run · all repros

Contents
  1. The fix01
  2. Upgraded Node and now see “is not a function”?02
  3. TypeScript compiled to CommonJS03
  4. The other new error: ERR_REQUIRE_ASYNC_MODULE04
  5. Why it happens05
  6. How this was tested06

ERR_REQUIRE_ESM means CommonJS code (require) tried to load a package that only ships as an ES module. Many popular packages went ESM-only in a major version: chalk 5, node-fetch 3, got 12, nanoid 4 and more. Whether you get the error depends almost entirely on your Node version, so I ran the same code on five of them:

Node require() an ESM-only package require() an ES module with top-level await
20.20.2 ✅ loads ❌ ERR_REQUIRE_ASYNC_MODULE
22.11.0 ❌ ERR_REQUIRE_ESM ❌ ERR_REQUIRE_ESM
22.12.0 ✅ loads, with an ExperimentalWarning ❌ ERR_REQUIRE_ASYNC_MODULE
24.22.1 ✅ loads ❌ ERR_REQUIRE_ASYNC_MODULE
26.13.0 ✅ loads ❌ ERR_REQUIRE_ASYNC_MODULE

So on a current Node, plain require() of an ES module works, and ERR_REQUIRE_ESM mostly comes from Node 22.11 and older 22.x, or from older Node 20 and 18 releases, which I didn’t test here. Note the Node 20 row: the current 20.x release loads ES modules with require() too.

The fix

Option 1: use a dynamic import() from CommonJS. It works on every Node version, old or new:

(async () => {
  const { default: chalk } = await import("chalk");
  console.log(chalk.green("works"));
})();

Option 2: upgrade Node. On 22.12 and newer, and on the current Node 20 release, the code that throws ERR_REQUIRE_ESM on 22.11 just runs. If you’re stuck on an old version anyway, this is the least-effort fix. After upgrading, read the next section: the package’s default export moves.

Option 3: pin the last CommonJS version of the package, if one exists (for chalk that’s chalk@4). Or convert your own project to ESM with "type": "module" and use import everywhere.

Upgraded Node and now see “is not a function”?

This is the trap after the upgrade. require() of an ES module returns the module namespace, so the package’s default export sits under .default. On every version where require("chalk") loaded, chalk.green was undefined:

TypeError: chalk.green is not a function

Add .default:

const chalk = require("chalk").default;
console.log(chalk.green("works"));

On Node 22.12 the load also printed a warning, which is harmless and gone in Node 24:

ExperimentalWarning: CommonJS module .../a.cjs is loading ES Module .../node_modules/chalk/source/index.js using require().

TypeScript compiled to CommonJS

A very common way into this error: your TypeScript says import chalk from "chalk", but tsc compiles it to require("chalk") because module is commonjs. The compiled file failed on Node 22.11.0 with the same error:

Error [ERR_REQUIRE_ESM]: require() of ES Module .../node_modules/chalk/source/index.js from .../out/g.cjs not supported.

On 20.20.2, 22.12.0, 24 and 26 the same compiled file ran, and with esModuleInterop on, chalk.green worked without adding .default: TypeScript’s interop helper picks the default export for you. So for a TypeScript project, upgrading Node is usually the whole fix.

The other new error: ERR_REQUIRE_ASYNC_MODULE

require() still can’t load an ES module that uses top-level await, on any version:

Error [ERR_REQUIRE_ASYNC_MODULE]: require() cannot be used on an ESM graph with top-level await. Use import() instead. To see where the top-level await comes from, use --experimental-print-required-tla.

Load that module with import() instead:

import("./tla/index.js").then((m) => console.log(m.default));

If you wrote the top-level await in a .cjs file yourself, you get a different error, because CommonJS can’t contain it at all:

Warning: Failed to load the ES module: ...\f.cjs. Make sure to set "type": "module" in the nearest package.json file or use the .mjs extension.
SyntaxError: await is only valid in async functions and the top level bodies of modules

Wrap the code in an async function, or make the file an ES module (.mjs, or "type": "module").

Why it happens

Node has two module systems: CommonJS (require) and ES modules (import). For years require() refused ES modules outright, which is ERR_REQUIRE_ESM. Node 22.12 turned on require() of ES modules by default, and the current Node 20 release does it too, as long as the module graph has no top-level await. That’s why the same project fails on one machine and works on another: check node -v first.

How this was tested

October 31, 2026. The same folder (chalk 5.6.2, an ES module with top-level await, and a TypeScript file compiled to CommonJS with TypeScript 6 and esModuleInterop) ran on Node 20.20.2, 22.11.0, 22.12.0, 24.22.1 and 26.13.0 on GitHub Actions ubuntu-latest, and the top-level await cases on Node 24.14.0 and 26.11.1 on Windows 11 Pro. The first version of this post (September) simulated old Node with --no-experimental-require-module on Node 24; this version uses the real releases. The script and the full output are public.

— N.K., end of entry No.005

Useful? Pass it on:Post on XFollow @EmotionalMatter

Related entries

  1. No.026

    Fix: Dynamic require of "react" / "fs" is not supported

    esbuild's ES module output throws this for a require() it left in the bundle. Four fixes tested on Node 24, plus the case only Cloudflare Workers hits.

    > throw Error('Dynamic require of "' + x + '" is not supported');

    FIXED3 min
  2. No.023

    Fix: TypeScript enum is not supported in strip-only mode

    Node's ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX for enum, parameter properties, namespace, export = and import =. Two ways to run it unchanged, both tested.

    > enum Color { Red, Green }

    FIXED4 min
  3. No.014

    Fix: This syntax is not allowed when 'erasableSyntaxOnly' is enabled

    TS1294: TypeScript rejects your enum, namespace or constructor shorthand. Why new projects turn this on, what each piece becomes, and when to switch it off.

    > src/a.ts(1,6): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.

    FIXED3 min

Post card · Every Sunday

What broke this week.

One email on Sundays: the Node, TypeScript, Python and AI SDK releases that broke builds that week, each one reproduced, with a link to the fix that worked. Never shared, and you can leave any time.

— Nilay

or follow by RSSor on X

By subscribing you agree to the privacy note. One click to leave.

tip: paste the exact error text