Vitest / Jest Out of Memory (SIGKILL / exit 137) - Fix Test OOM in CI
Test runners fan out across worker processes, each holding the module graph and test state. Too many workers, leaked handles, or a heap-hungry suite can exhaust runner memory and get killed.
What this error means
A test job dies with JavaScript heap out of memory (V8 hitting its own ceiling) or is SIGKILLed with exit 137 (the OS OOM killer). The failing test is often not the cause - total memory across workers is.
FATAL ERROR: Reached heap limit Allocation failed -
JavaScript heap out of memory
# or, from the OS:
Killed
##[error]Process completed with exit code 137.Common causes
Too many parallel workers for the runner
By default the runner spawns workers per CPU. On a memory-constrained runner, the sum of all worker heaps exceeds available RAM and the OS kills the process (exit 137).
Leaked memory or open handles in tests
Tests that never close servers, timers, or DB connections, or accumulate large fixtures, grow memory across the run until V8 or the OS aborts it.
A genuinely heap-heavy suite
Large snapshots, big in-memory data, or heavy module graphs can cross V8’s default heap ceiling, producing the fatal heap error.
How to fix it
Limit workers and raise the heap modestly
Reduce parallelism so total memory fits, and lift the V8 limit if a single worker needs it.
# Vitest
vitest run --pool=threads --poolOptions.threads.maxThreads=2
# Jest
jest --maxWorkers=2 --workerIdleMemoryLimit=512MB
# raise per-process heap if needed
NODE_OPTIONS=--max-old-space-size=2048 npm testFind and fix leaks
- Run Jest with
--detectOpenHandlesto surface unclosed resources. - Tear down servers, timers, and connections in afterEach/afterAll.
- Shard large suites across jobs instead of one giant run.
How to prevent it
- Set worker count relative to runner memory.
- Close all handles in test teardown.
- Shard heavy test suites in CI.