CI "Cannot allocate memory" - Fix ENOMEM on Runners
A syscall asked the kernel for memory and was refused with ENOMEM. Unlike a SIGKILL, the process survives to report the error - but the underlying cause is the same: not enough memory on the runner.
What this error means
A tool fails with Cannot allocate memory, OSError: [Errno 12], or mmap failed. The process is still alive to print the error, but it could not grow its heap, map a file, or spawn a thread because the allocation was denied.
fatal error: runtime: cannot allocate memory
# or
OSError: [Errno 12] Cannot allocate memory
# or
java.lang.OutOfMemoryError: unable to create new native threadCommon causes
The runner is out of usable RAM and swap
Other processes plus the failing one exhausted physical memory. With little or no swap on a CI runner, the next allocation is simply refused.
A cgroup memory limit blocks the allocation
A container or systemd cgroup with a memory.max/--memory limit will deny allocations once the cgroup reaches its ceiling, even when the host has free RAM.
Overcommit or address-space limits
A low vm.overcommit_memory setting, an ulimit -v (virtual memory) cap, or a 32-bit process can refuse a large mmap/malloc regardless of free RAM.
How to fix it
Check what memory is available
See real usage and any cgroup limit before changing resources.
free -m
cat /sys/fs/cgroup/memory.max 2>/dev/null
ulimit -vAdd memory or raise the limit
- Run on a larger runner, or raise the container
--memoryceiling. - Lower the process’s own memory use (smaller heap, fewer threads, less parallelism).
- If
ulimit -vis set too low, raise it for the step that needs it.
How to prevent it
- Size runners so peak RAM stays comfortably under the limit.
- Avoid hard
ulimit -vcaps unless you have a specific reason. - Cap thread pools and parallel workers to bound memory growth.