FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory in the CI jest run - how to fix
Fixes Node heap exhaustion during jest runs in CI. Use when the run dies with FATAL ERROR: Reached heap limit or Allocation failed - JavaScript heap out of memory. Covers raising the heap with NODE_OPTIONS, cutting worker memory pressure, and finding the leak with open-handle and heap logging. Not for out-of-memory in the application under test.
TL;DR
Node's default heap is about 2 GB on 64-bit systems, and a large jest suite with source maps and transforms can exceed it, especially on CI runners with less RAM than a laptop. Raise the heap with NODE_OPTIONS=--max-old-space-size in the CI job, reduce memory pressure with fewer workers, and hunt the actual leak with --detectOpenHandles and --logHeapUsage before settling for a bigger heap as the permanent answer.
The query
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory in the CI jest run - how to fixUse this when
- jest dies in CI with FATAL ERROR: Reached heap limit
- Allocation failed - JavaScript heap out of memory appears in the CI output
- the suite passes locally on a machine with more RAM
Not for
- the application under test runs out of memory (profile the app, not the test runner)
- the container is OOM-killed with no FATAL ERROR line (raise the container memory, not the Node heap)
- a single test file OOMs in isolation (that file has the leak; skip straight to step 4)
Steps
1. Confirm the OOM signature in the CI log
Make sure the death is really heap exhaustion and not a worker crash or an OS-level OOM kill. The FATAL ERROR line with Allocation failed is the signature.
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memoryExpected output: the log shows the heap-limit signature, not a segfault or a container OOM-kill.
2. Raise the heap in the CI job
Set NODE_OPTIONS in the test step's environment. Size it below the runner's RAM: 6144 on an 8 GB runner leaves room for the OS and the workers.
- name: Run jest
env:
NODE_OPTIONS: --max-old-space-size=6144
run: npx jest --ciExpected output: the run gets past the previous death point or completes.
3. Reduce worker memory pressure
Each jest worker holds its own heap. Fewer workers means a lower peak, at the cost of a slower run. This also helps when the heap raise alone is not enough.
NODE_OPTIONS=--max-old-space-size=6144 npx jest --ci --maxWorkers=2Expected output: peak memory drops and the run is stable across repeated CI runs.
4. Find the leak instead of renting a bigger heap forever
Run once with heap logging and open-handle detection to find what actually grows: usually a module that accumulates state across test files, or transforms caching too aggressively.
npx jest --ci --maxWorkers=2 --logHeapUsage --detectOpenHandles 2>&1 | tail -30Expected output: the leaking module or handle is identified and fixed, so the heap raise becomes headroom, not a crutch.
Tool compatibility
- jest 26 - 30
- Node 16 - 22
- any CI provider
Variant phrasings
- FATAL ERROR: Reached heap limit Allocation failed
- JavaScript heap out of memory in the CI jest run
- jest worker process ran out of memory
Why it happens
V8 caps the heap well below the machine's RAM by default, and jest's per-file transform cache, source maps, and jsdom environments all allocate heavily. CI runners typically have 4 to 8 GB of RAM versus 16 to 32 GB on a laptop, so a suite that fits comfortably on a developer machine exceeds the default heap in CI.
Edge cases / pitfalls
- never set the heap above the runner's physical RAM: the OS will OOM-kill the process, which is harder to diagnose than the FATAL ERROR
- ts-jest with isolatedModules transpiles faster and uses less memory than full type-checking per file
- --maxWorkers=50% is a good default on large runners, but on small CI runners an explicit small number wins
- coverage collection roughly doubles transform memory; if OOM appears only with --coverage, split the coverage run from the test run
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_EC1PHaypWvZgTsAiZRvzqA