Short answer
Upgrade to Node.js 20.19 or 22.12 or later, where require() can load ES modules that have no top-level await (a default export then sits at .default). If you can’t upgrade, load the package with await import('pkg') inside an async function, switch your project to ES modules ("type": "module"), or pin the last CommonJS version (node-fetch@2, chalk@4). If the error comes from a tool such as Jest or ts-node, configure that tool for ES modules, because it may still use the old loader.
Why require() rejects the module, and the fix
01
The Node.js version is too old for require(esm)
“v23.0.0, v22.12.0, v20.19.0 This feature is no longer behind the --experimental-require-module CLI flag.” Node.js, Modules: Loading ECMAScript modules using require()
Loading ES modules with require() is on by default from Node.js 20.19 and 22.12. On older versions the same line throws ERR_REQUIRE_ESM. Check node -v locally and on the server, CI and hosting platform, and set the version in package.json engines or .nvmrc. After upgrading, require() returns the module namespace object, so a default export is at .default: const chalk = require('chalk').default.
node -v // package.json "engines": { "node": "^20.19.0 || >=22.12.0" } // default exports sit at .default const chalk = require('chalk').default;02
The module uses top-level await
“require() only supports loading ECMAScript modules that meet the following requirements: The module is fully synchronous (contains no top-level await)” Node.js, Modules: Loading ECMAScript modules using require()
Even on new Node.js versions, require() can only load an ES module that runs synchronously. A module with top-level await (in it or in its imports) fails with ERR_REQUIRE_ASYNC_MODULE. Load it with import() instead.
// import() works for any ES module, with or without top-level await async function main() { const { default: fetch } = await import('node-fetch'); const res = await fetch('https://example.com'); } main();03
Move the project to ES modules
If most of your dependencies are ES modules now, switching your own code is the lasting fix: add "type": "module" to package.json and replace require() and module.exports with import and export. Rename files that must stay CommonJS to .cjs.
// package.json { "type": "module" } // before: const chalk = require('chalk'); import chalk from 'chalk';04
Pin the last CommonJS version
When neither upgrading nor converting is possible right now, install the last major version that still ships CommonJS, such as node-fetch@2 or chalk@4. Treat it as temporary, because those versions stop getting fixes. On Node.js 18 and later, the built-in fetch removes the need for node-fetch altogether.
npm install node-fetch@2
Checked against the vendor’s docs on : Node.js: Modules: Loading ECMAScript modules using require(); Node.js: Modules: Packages ("type" and file extensions).
Rather hand it over?
Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.
- from $450App Fix TicketOne reproducible bug in an existing mobile or web app, diagnosed and fixed.See scope and start
- from $450AI-Built App RescueA Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.See scope and start
Related: “Cannot use import statement outside a module” · Node.js “Cannot find module” · Node.js ERR_OSSL_EVP_UNSUPPORTED · Node.js ERR_INVALID_ARG_TYPE