- Node.js
JavaScript heap out of memoryの直し方|Node.js
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory は、Node.js が JavaScript のデータを置くメモリ(ヒープ)の上限に達し、それ以上確保できずに強制終了したときのエラーです。 ビルド(webpack・Vite・Next.js・TypeScript)や、大きなファイル・大量のデータを扱う処理で起きます。
対処は2段階です。
| 段階 | やること |
|---|---|
| 1. すぐに動かす | ヒープの上限を上げる:NODE_OPTIONS=--max-old-space-size=4096(単位は MB) |
| 2. 原因を減らす | 全部を一度にメモリに載せる処理を、少しずつ処理する形にする。もれがないかをヒープスナップショットで確かめる |
確認環境:Node.js 22.22.2、Linux(メモリ 8GB)(確認日 2026年10月11日)。ヒープの上限を小さくして再現しました。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「JavaScript heap out of memoryの直し方|Node.js」
再現:配列にデータを入れ続ける
const rows = [];
let i = 0;
while (true) {
rows.push({ id: i, name: "user" + i, tags: ["a", "b", "c"], created: new Date().toISOString() });
i++;
}
$ node --max-old-space-size=64 leak.js
200000 件 heapUsed=39MB
<--- Last few GCs --->
[4596:0x381be000] 981 ms: Mark-Compact (reduce) 62.3 (66.1) -> 62.3 (66.1) MB, ...
[4596:0x381be000] 1036 ms: Mark-Compact (reduce) 62.8 (66.1) -> 62.6 (66.3) MB, ...
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----
1: 0xe42d60 node::OOMErrorHandler(char const*, v8::OOMDetails const&) [node]
...
$ echo $?
134
| 表示 | 読み方 |
|---|---|
Last few GCs の 62.3 -> 62.3 MB |
ガベージコレクション(不要なメモリの回収)をしてもほとんど減らない=使い続けているデータでいっぱい |
Mark-Compact (reduce) が続く |
回収を何度も試みている。直前は処理がとても遅くなる |
終了コード 134 |
強制終了(abort)。try/catch では捕まえられない |
まず確認:今のヒープの上限はいくつか
node -e "console.log(Math.round(require('v8').getHeapStatistics().heap_size_limit / 1048576) + 'MB')"
| 条件(確認環境) | heap_size_limit |
|---|---|
| 何も指定しない(メモリ 8GB のマシン) | 2096MB |
--max-old-space-size=256 |
304MB |
--max-old-space-size=4096 |
4144MB |
既定の上限は、マシンのメモリによって決まります(Node.js 公式の学習ガイドでも、上限はシステムのメモリに基づくとされています)。指定した値より少し大きく表示されるのは、--max-old-space-size が「長く使うデータの領域(Old Space)」だけの上限で、ほかの領域が足されるためです。
NODE_OPTIONS がどこかで設定されていないか
確認環境では、環境変数 NODE_OPTIONS に --max-old-space-size=8192 が設定されていたため、何も指定していないつもりでも上限は 8GB 台になっていました。CI・Docker のイメージ・シェルの設定ファイルで設定されていることがあります。
node -p "process.env.NODE_OPTIONS"
直し方1:ヒープの上限を上げる
| 実行のしかた | 書き方 |
|---|---|
| node を直接実行 | node --max-old-space-size=4096 app.js |
| npm scripts・ビルドツール | NODE_OPTIONS=--max-old-space-size=4096 npm run build |
| package.json に書く | "build": "NODE_OPTIONS=--max-old-space-size=4096 vite build"(Windows も使うなら cross-env を使う) |
| PowerShell | $env:NODE_OPTIONS="--max-old-space-size=4096"; npm run build |
| GitHub Actions | env: に NODE_OPTIONS: --max-old-space-size=4096 |
npm run build のように、node を直接実行しない場合は NODE_OPTIONS を使います。確認環境でも、NODE_OPTIONS=--max-old-space-size=512 npm run ... で起動した node の上限は 560MB になり、npm が起動する node に引き継がれました。
NODE_OPTIONS とコマンドラインの両方に書いたとき
$ NODE_OPTIONS=--max-old-space-size=256 node --max-old-space-size=1024 -e "..."
1072 ← コマンドラインの 1024 が使われた
両方にあると、コマンドラインの指定が使われました。 上限を上げたのに変わらないときは、コマンドライン側に小さい値が書かれていないかも確かめます。
いくつにするか
| 目安 | 理由 |
|---|---|
| マシン(コンテナ)のメモリより小さく | ヒープのほかにも、Node.js 自体・ネイティブのメモリ・ほかのプロセスがメモリを使う |
| CI のランナーのメモリを確かめる | ランナーのメモリを超えると、Node.js のエラーではなく OS やコンテナに強制終了される |
| 上げても落ちるなら、上げるのをやめて原因を探す | もれ(使い終わったデータが解放されない)なら、いくら上げても落ちる |
直し方2:全部を一度に載せない
44MB・200万行の CSV を合計する処理で比べました。
// 全部読み込んでから処理する
const lines = fs.readFileSync(file, "utf8").split("\n").slice(1).filter(Boolean);
const rows = lines.map(l => { const [id, name, amount] = l.split(","); return { id: +id, name, amount: +amount }; });
console.log("合計", rows.reduce((s, r) => s + r.amount, 0));
// 1行ずつ読みながら処理する
const rl = readline.createInterface({ input: fs.createReadStream(file) });
let total = 0, first = true;
for await (const line of rl) {
if (first) { first = false; continue; } // 見出し行
if (!line) continue;
total += +line.split(",")[2];
}
| 書き方 | ヒープの上限 128MB | ヒープの上限 1024MB |
|---|---|---|
全部読み込む(readFileSync → split → map) |
JavaScript heap out of memory |
成功 |
| 1行ずつ読む(stream + readline) | 成功(heapUsed=5MB) | 成功 |
44MB のファイルでも、文字列の配列とオブジェクトの配列にすると、何倍ものメモリを使います。 1行ずつ処理すれば、ファイルが大きくなってもメモリはほとんど増えません。
| 起きやすい処理 | 見直し方 |
|---|---|
大きなファイル・CSV・JSON を readFileSync で読む |
stream で少しずつ処理する |
| DB から全件を取得して配列にする | ページングする、またはカーソル・stream で読む |
| 結果を全部配列にためてから書き出す | 処理しながら書き出す |
| キャッシュ用のオブジェクト・Map が増え続ける | 上限や有効期限を決める |
| ビルド(TypeScript の型チェック・ソースマップ) | 型チェックを別のプロセスに分ける、ソースマップの設定を見直す |
原因を探す:落ちる直前のヒープスナップショット
--heapsnapshot-near-heap-limit を付けると、上限に近づいたときに、ヒープの中身をファイルに書き出します。
$ node --max-old-space-size=64 --heapsnapshot-near-heap-limit=1 leak.js
Wrote snapshot to /srv/s4/Heap.20261011.002514.4928.0.001.heapsnapshot
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
書き出された .heapsnapshot を、Chrome の DevTools の Memory タブで「Load」して開くと、何のオブジェクトがメモリを使っているかが分かります(Node.js 公式の学習ガイドの手順)。確認環境では、64MB のヒープに対してスナップショットは約 156MB になりました。ディスクの空きを確かめてから使います。
確認の手順(チェックリスト)
| 順番 | 確認すること | 方法 |
|---|---|---|
| 1 | 今の上限 | v8.getHeapStatistics().heap_size_limit |
| 2 | NODE_OPTIONS の設定 | node -p "process.env.NODE_OPTIONS" |
| 3 | まず動かす | NODE_OPTIONS=--max-old-space-size=4096(マシンのメモリより小さく) |
| 4 | 全部を一度に載せていないか | readFileSync・全件取得・配列にためる処理 |
| 5 | もれがないか | --heapsnapshot-near-heap-limit=1 で書き出し、DevTools で開く |
| 6 | CI・コンテナ | ランナー・コンテナのメモリと、上限の値を合わせる |
よくある質問
Q. 上限を上げたのに、まだ落ちます。 A. 使い終わったデータが解放されない「もれ」の可能性があります。上限を上げると落ちるまでの時間が延びるだけなので、ヒープスナップショットで、何が増え続けているかを確かめます。
Q. try / catch で捕まえて続けられますか。 A. できません。このエラーは JavaScript の例外ではなく、Node.js のプロセスそのものが強制終了します(確認環境の終了コードは 134)。サーバーなら、プロセスの再起動の仕組み(PM2・systemd・コンテナの再起動)と、原因の対処を組み合わせます。
まとめ
- Node.js のヒープ(JavaScript のメモリ)が上限に達して強制終了。try/catch では捕まえられない
- まず
heap_size_limitとNODE_OPTIONSで今の上限を確かめる - すぐ動かすなら
NODE_OPTIONS=--max-old-space-size=4096(単位 MB、マシンのメモリより小さく) - コマンドラインの指定は NODE_OPTIONS より優先された
- 根本は 全部を一度に載せない。stream で1行ずつ処理すると、128MB でも動いた
- もれは
--heapsnapshot-near-heap-limitで書き出して、DevTools の Memory タブで探す
参考・出典
確認日はいずれも 2026年10月11日です。
- Node.js「Understanding and Tuning Memory」:https://nodejs.org/en/learn/diagnostics/memory/understanding-and-tuning-memory
- Node.js「Using Heap Snapshot」:https://nodejs.org/en/learn/diagnostics/memory/using-heap-snapshot
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「JavaScript heap out of memoryの直し方|Node.js」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。