Skip to content
Latchkey

Node.js "Must use import to load ES Module" (CJS requiring ESM) in CI

A CommonJS module called require() on a package that is ESM-only. CommonJS cannot synchronously require an ES module, so Node throws and tells you to use import instead.

What this error means

A build or script that uses require() fails after a dependency upgrade. The dependency moved to ESM-only, and the surrounding code is still CommonJS.

node
Error [ERR_REQUIRE_ESM]: require() of ES Module
/work/repo/node_modules/chalk/source/index.js not supported.
Instead change the require of index.js to a dynamic import().
  code: 'ERR_REQUIRE_ESM'

Diagnose it: what is different about the runner?

A build that passes locally and fails on a runner differs in a small number of predictable ways. Check those before changing build configuration, because the build config is usually not the thing that changed.

.github/workflows/ci.yml
- run: |
    node --version && npm --version
    echo "NODE_ENV=$NODE_ENV  CI=$CI"
    nproc && free -h && df -h /
    ls -la node_modules/.bin | head

Common causes

A dependency went ESM-only

Popular packages have dropped CommonJS. A major upgrade switches them to ESM, and any require() of them now throws.

Your code is CommonJS

The project compiles or runs as CommonJS, so it uses require. ESM-only deps cannot be required synchronously from that context.

How to fix it

Convert the consumer to ESM

Make the project ESM so it can import the dependency natively.

  1. Add "type": "module" to package.json (or compile to ESM).
  2. Replace require(...) with import ....
  3. Use module/moduleResolution of NodeNext if using TypeScript.

Or pin the last CommonJS version

If converting is not feasible now, pin the dependency to its final CommonJS release.

Terminal
npm install chalk@4

The three that account for most of them

  • Case sensitivity. Linux runners are case sensitive, macOS is not. An import with the wrong case resolves locally and fails in CI.
  • Out of memory. Exit code 137 is a SIGKILL from the kernel, not a build error. Raise --max-old-space-size or use a larger runner.
  • devDependencies pruned. NODE_ENV=production makes npm ci skip devDependencies, so the build tool itself goes missing. Set it after install, not before.

How to prevent it

  • Decide on a module system (ESM) and keep the project consistent.
  • Read major-version changelogs for ESM-only migrations before upgrading.
  • Use import() dynamic import where a CommonJS context must load ESM.

Frequently asked questions

What causes Node.js "Must use import to load ES Module" (CJS requiring ESM) in CI?
There are 2 common causes: a dependency went esm-only and your code is commonjs. Popular packages have dropped CommonJS.
How do I fix Node.js "Must use import to load ES Module" (CJS requiring ESM) in CI?
There are 2 fixes depending on which cause you have: convert the consumer to esm and or pin the last commonjs version. Work through them in order, since the first is the most common.
What does Node.js "Must use import to load ES Module" (CJS requiring ESM) in CI actually mean?
A build or script that uses require() fails after a dependency upgrade.
How do I stop Node.js "Must use import to load ES Module" (CJS requiring ESM) in CI happening again?
Decide on a module system (ESM) and keep the project consistent. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card