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.
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.
- run: |
node --version && npm --version
echo "NODE_ENV=$NODE_ENV CI=$CI"
nproc && free -h && df -h /
ls -la node_modules/.bin | headCommon 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.
- Add
"type": "module"to package.json (or compile to ESM). - Replace
require(...)withimport .... - Use
module/moduleResolutionof NodeNext if using TypeScript.
Or pin the last CommonJS version
If converting is not feasible now, pin the dependency to its final CommonJS release.
npm install chalk@4The 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-sizeor use a larger runner. - devDependencies pruned.
NODE_ENV=productionmakesnpm ciskip 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.