Coding Agents & Terminal · recorded 2026-08-29 · applies to 2 tool(s) ✓ Verified

Problem: Build crashes with "JavaScript heap out of memory" (FATAL ERROR: Reached heap limit) —— Trove problem library

Verified 2026-08-29Node build fails with heap out of memory — raise the cap temporarily: NODE_OPTIONS=--max-old-space-size=8192 (size to your machine).

Quick fix

# One-liner: temporarily raise the cap (size depends on machine RAM, e.g. 4096/8192)
NODE_OPTIONS=--max-old-space-size=8192 npm run build

What you will run into

Frontend build/typecheck (webpack, vite, vue-tsc, jest...) crashes midway; the last console lines are FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory.

Bigger projects trigger it more easily (many dependencies / huge single files / full tsc typecheck); retries may pass occasionally; it happens at npm run build / vue-tsc / CI packaging stage.

Why this happens

Node's V8 engine sets a default cap on the JS heap; once exceeded, GC can't reclaim enough and V8 gives up and crashes.

The default cap is not fixed at 2G: modern Node (64-bit) defaults to ~4GB (measured on this machine, Node 22: heap_size_limit = 4144MB); older versions or 32-bit are smaller (1.5~2G) — the "default 2G" in many online tutorials reflects old versions.

Build tools keep the whole dependency graph + compiled output in memory, so a big project hits the cap.

V8 sets a "default heap cap" because: when the heap gets too large, GC pauses (mark-sweep) freeze the main thread for too long, so V8 prefers OOM over unbounded growth.

The cap depends on architecture and version, not a fixed 2G: modern 64-bit Node defaults to ~4GB (Node 22 measured heap_size_limit=4144MB); older/32-bit versions are smaller — "default 2G" is an old-version fact.

Build tools hold the whole dependency graph plus artifacts in memory, so large projects hit the cap.

Deterministic takeaway: on OOM, read the actual heap_size_limit (node -e "console.log(require('v8').getHeapStatistics.heap_size_limit)"), do not trust stale online numbers;

two correct paths — raise the cap with --max-old-space-size (NODE_OPTIONS=--max-old-space-size=8192 in build scripts, matched to machine memory) or reduce peak usage (batching, streaming);

OOM in CI is often because the container memory limit is smaller than the default cap — check the container quota first; fixed diagnostic: heap out of memory + build-like task = cap problem; the FATAL ERROR section prints the limit at the time.

Step by step

1. Temporarily raise the cap (fastest) — Required

Three equivalent forms:

node --max-old-space-size=8192 ./node_modules/vite/bin/vite.js build

Or the env var (CI/Jenkins/Windows friendly): NODE_OPTIONS=--max-old-space-size=8192; or in package.json:

"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vite build"

On Windows, use cross-env to avoid quoting issues. Don't exceed physical RAM by much, or the machine thrashes into swap.

2. Long-term optimization (root fix) — Required

Build caching (webpack cache / vite cache), code splitting / lazy loading, upgrading the build tool (webpack→vite), moving vue-tsc --noEmit to a separate stage, trimming dependencies.

Memory pressure comes from "too much held in memory at once"; raising the cap just moves the line up.

3. Distinguish system OOM — Required

If the error is Killed or Exit status 137 (in containers/CI), that's the OS killing it (cgroup/container memory limit) — raising --max-old-space-size won't help; add container memory or reduce concurrency.

How to confirm it works

Build passes after raising the cap (measured output shape):

node --max-old-space-size=8192 <your-script> → allocated up to 6000MB cap, exited fine (exit 0)
NODE_OPTIONS=--max-old-space-size=8192 node <your-script> → same success (exit 0; env var equivalent to CLI)

With the default cap → FATAL ERROR + SIGABRT, exit code 134 (measured).

Other environments

EnvironmentNotes
Default capModern Node ~4GB (measured 4144MB); older/32-bit smaller
CLInode --max-old-space-size=8192 ...
Env varNODE_OPTIONS=--max-old-space-size=8192 (CI/Windows friendly)
package.jsoncross-env avoids quoting issues
System OOMKilled/137 = container memory cap, not the V8 heap

Symptom

Front-end builds (webpack, vite, vue-tsc, jest, etc.) crash mid-way; the last console lines are:

<--- Last few GCs --->
.... MB: Mark-Compact ... allocation failure; scavenge might not succeed

<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----

Older Node versions word the same error as FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory. Signs: bigger projects trigger it more often (many deps / huge single files / full tsc type-check); retrying may pass randomly; happens during npm run build / vue-tsc / CI packaging.

Cause

Node's V8 engine caps the JS heap; once the cap is hit and GC can't reclaim, V8 aborts. The default cap is not fixed at 2G: modern Node (64-bit) defaults to ~4GB (measured 4144MB heap_size_limit on Node 22 here); older or 32-bit versions are smaller (1.5~2G) — the "default 2G" claim in many tutorials reflects old versions. Build tools hold the whole dependency graph plus compiled output in memory, so large projects hit the cap.

Solution

In recommended order:

  1. Raise the limit temporarily (fastest) — three equivalent forms:
  • CLI: node --max-old-space-size=8192 ./node_modules/vite/bin/vite.js build (same for webpack / vue-tsc);
  • Env var (CI/Jenkins/Windows friendly): NODE_OPTIONS=--max-old-space-size=8192; permanent on Windows: setx NODE_OPTIONS "--max-old-space-size=8192" (restart the terminal afterwards);
  • In package.json: "build": "node --max-old-space-size=8192 ./node_modules/vite/bin/vite.js build"; on Windows use cross-env NODE_OPTIONS=--max-old-space-size=8192 vite build to avoid quoting issues.

Size the value to your machine's RAM (e.g. 4096/8192); don't exceed physical memory by much or the machine thrashes on swap.

  1. Long-term optimization (root cause): build caching (webpack cache / vite cache), code splitting / lazy loading, upgrade the bundler (webpack→vite), move vue-tsc --noEmit to a separate stage, trim dependencies. Pressure comes from "too much in memory at once" — raising the limit only moves the line.
  2. Distinguish OS-level OOM: if the error is Killed or Exit status 137 (containers/CI), the OS killed the process (cgroup/container memory limit); --max-old-space-size won't help — raise container memory or reduce concurrency.
Verification Evidence
  • Local repro (2026-08-29, WSL Ubuntu, Node v22.22.1):
  • Default heap_size_limit measured at 4144MB (v8.getHeapStatistics), showing the "default 2G" claim is outdated for modern Node; --max-old-space-size=8192 raises it to 8240MB;
  • A script growing large arrays under the default limit → full reproduction of FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory (with Last few GCs / JS stacktrace / Native stack trace), SIGABRT exit 134;
  • node --max-old-space-size=8192 <your-script> → survives past 6000MB allocation cap, exit 0;
  • NODE_OPTIONS=--max-old-space-size=8192 node <your-script> → same success (exit 0), proving the env-var form equals the CLI form;
  • The article's package.json approach (invoking vite.js via node) is a variant of the CLI form, verified by the same mechanism.

Evidence details kept locally (2026-08-29)

Applicable tools (2)

This problem is linked from the tool pages below — reachable from either side.

nodenpm

Source & evidence

Recorded Verified ✓ VerifiedApplies to 2 tool(s)
Entries contain locally measured or reviewable-source solutions; unmeasured items are explicitly labeled.

Source: https://www.cnblogs.com/c2g5201314/p/19070905

← Coding Agents & Terminal domain | Problem Catalog Experience | Facing another issue? Go to the Helpdesk