Node.js で「Error [ERR_REQUIRE_ESM]」が解消できない
ESM 専用パッケージを CommonJS の require() で読み込もうとすると ERR_REQUIRE_ESM になる。
動的 import() を await する、package.json を type:module に切り替える、または ESM 化前のバージョンに固定する。
公開: 更新:
要約
Error [ERR_REQUIRE_ESM]: require() of ES Module ... not supported. は、require() で ESM 専用 パッケージを読もうとして拒否された状態。まず Node のバージョンを確認する: require(esm) は Node 20.19 / 22.12 以降では既定で有効になり、ESM を require() してもこのエラーは出ない。
それでも出るなら Node がこれより古いか、対象 ESM が top-level await を含む(その場合は別エラー ERR_REQUIRE_ASYNC_MODULE になる)。
確実な対処は動的 import() で、ほかに type:module 化・バージョン pin・Node の更新がある。
よくある原因
- ESM only への更新:
chalk@5/node-fetch@3/nanoid@4のように、メジャー更新で ESM only に切り替えたパッケージを CJS から require している。 - モジュール構文の混在: CJS 前提のプロジェクトで
import構文を混ぜているが、tsc / Babel の出力が require のまま。 - type 未指定:
package.jsonに"type":"module"が無いと Node は.jsを CJS として扱う。 - Node が 20.19 / 22.12 未満: これらの版より前は
require(esm)が既定で無効なため、ESM only を require した瞬間にERR_REQUIRE_ESMになる。
20.19 / 22.12 以降は既定で require できるが、対象 ESM が top-level await を含むと別エラーERR_REQUIRE_ASYNC_MODULEに変わる。
解決策
1. 動的 import を await する
// CJS プロジェクトのまま、関数内で取り込む
async function main() {
const { default: chalk } = await import("chalk");
console.log(chalk.green("ok"));
}
main();CJS のトップレベルでは await が使えないため関数で囲む。公式 ESM ドキュメント のとおり、動的 import() は ESM / CJS どちらからも呼べる唯一の橋渡し。
2. プロジェクトを ESM 化
package.json に追記する。
{
"type": "module"
}これで .js が ESM 扱いになり、import { x } from "pkg" がそのまま使える。require を残したいファイルだけ拡張子を .cjs に変える。
3. CJS 対応の最終版に pin
npm install chalk@^4移行が間に合わない既存コードに対しては、ESM 化前の最終メジャーに固定する暫定策。^5 などに上げ直す前に、テストが通る状態を作る。
4. Node を 20.19 / 22.12 以降に上げる(require(esm) が既定で有効)
require(esm)(CJS から ESM を require() する機能)は Node 22.12.0 で unflag され、20.19.0 にもバックポートされて、現在は stable・フラグ不要で既定有効。
これらの版に上げれば、ESM only パッケージも require() でそのまま読める(Node.js Modules ドキュメント)。
ただし対象の ESM(または依存)が top-level await を含む場合は、新しい Node でも require() できず ERR_REQUIRE_ASYNC_MODULE になる — このケースだけは Node を上げても解決しないので、解決策 1 の動的 import() を使う。
逆に旧来どおりの挙動に戻したい CI などでは、--no-experimental-require-module を付けると require(esm) を無効化できる。
実行例
実際に上記の手順を Node.js v20.20.2(Debian GNU/Linux 12 bookworm)環境で実行すると、素の require() は終了コード 0 で通る一方、--no-experimental-require-module を付けると ERR_REQUIRE_ESM(終了コード 1)が再現し、top-level await を含む ESM では新しい Node でも ERR_REQUIRE_ASYNC_MODULE(終了コード 1)が発生することが確認できる。
== versions ==
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
v20.20.2
v10.4.1
== run ==
--- Node.js バージョン ---
v20.20.2
--- npm install ---
npm install 終了コード: 0
--- 現行 Node: require(esm) が既定で有効なので素の require は通る ---
[Module: null prototype] {
__esModule: true,
default: 'hello from esm'
}
終了コード: 0
--- 旧挙動の再現: --no-experimental-require-module で ERR_REQUIRE_ESM ---
/tmp/tmp.woC4L30kHo/use-require.js:1
const pkg = require("esm-pkg");
^
Error [ERR_REQUIRE_ESM]: require() of ES Module /tmp/tmp.woC4L30kHo/esm-pkg/index.js from /tmp/tmp.woC4L30kHo/use-require.js not supported.
Instead change the require of index.js in /tmp/tmp.woC4L30kHo/use-require.js to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (/tmp/tmp.woC4L30kHo/use-require.js:1:13) {
code: 'ERR_REQUIRE_ESM'
}
Node.js v20.20.2
終了コード: 1
--- top-level await を含む ESM: 新 Node でも ERR_REQUIRE_ASYNC_MODULE ---
node:internal/modules/esm/module_job:433
throw new ERR_REQUIRE_ASYNC_MODULE(filename, parentFilename);
^
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.
From /tmp/tmp.woC4L30kHo/use-require-tla.js
Requiring /tmp/tmp.woC4L30kHo/esm-tla.mjs
at ModuleJobSync.runSync (node:internal/modules/esm/module_job:433:13)
at ModuleLoader.importSyncForRequire (node:internal/modules/esm/loader:389:47)
at loadESMFromCJS (node:internal/modules/cjs/loader:1363:24)
at Module._compile (node:internal/modules/cjs/loader:1503:5)
at Module._extensions..js (node:internal/modules/cjs/loader:1623:10)
at Module.load (node:internal/modules/cjs/loader:1266:32)
at Module._load (node:internal/modules/cjs/loader:1091:12)
at Module.require (node:internal/modules/cjs/loader:1289:19)
at require (node:internal/modules/helpers:182:18)
at Object.<anonymous> (/tmp/tmp.woC4L30kHo/use-require-tla.js:1:13) {
code: 'ERR_REQUIRE_ASYNC_MODULE'
}
Node.js v20.20.2
終了コード: 1
--- 万能策: 動的 import() を await で読み込む ---
動的 import の結果: hello from esm
終了コード: 0— 2026-06-05 時点の出力