GitHub Actions: "Process completed with exit code 137": a process killed for memory, and how much memory the runner has
Exit code 137 is 128 + 9: a process in the step ended with SIGKILL. Nothing in your code sends that signal, and on a GitHub-hosted runner it almost always comes from the kernel's out-of-memory killer, which picks a large process and kills it when the virtual machine runs out of memory. The step then fails, and the job goes on to report it. When the whole virtual machine is overwhelmed instead, the runner itself is lost ("The runner has received a shutdown signal").
What it looks like
The killed process prints nothing of its own. A shell or a task runner reports the kill, and the step fails with 137, or with 1 when a wrapper turns it into its own failure (microsoft/vscode #341818):
[eslint ] Killed ERROR: "eslint" exited with 137. ##[error]Process completed with exit code 1.
In a monorepo, the task runner names the package (desk-skills #409):
##[error]@repo/api#type-check: command (.../packages/api) pnpm run type-check exited (137) ##[error]Process completed with exit code 137.
It is usually intermittent. In vscode, ESLint was killed in 3 of the last 80 pull request runs on October 14 and 15, 2026, 4 minutes 45 seconds into its run, while the minified bundles were being built in parallel on the same runner (a larger runner of the project's own). In the other report, the same job passed on main before and after; there was nothing to fix on the branch. Whether it is killed depends on what else peaks at the same moment.
How much memory the runner has
From GitHub's reference for the standard runners (GitHub-hosted runners):
ubuntu-latest, the other Ubuntu labels and Windows: 16 GB with 4 CPUs in public repositories, 8 GB with 2 CPUs in private and internal repositories.ubuntu-slim: 5 GB with 1 CPU, in a container on a shared virtual machine.macos-latest,macos-15,macos-26andxcode-27(Apple Silicon): 7 GB with 3 CPUs. The Intel macOS labels: 14 GB.
So a job that passes in a public repository can be killed after it moves to a private one: it gets half the memory and half the CPUs.
Finding the process
- The line before the exit code usually names the command, as in the examples above. If it does not, run the steps one at a time in a test branch.
- On the Ubuntu runners you have
sudo, so a step after the failure can read the kernel's log of the kill:- if: failure() run: sudo dmesg -T | grep -i -E "out of memory|killed process" || true
- To see how close a step comes, run it under
/usr/bin/time -vand read "Maximum resident set size", or printfree -mbefore and after.
Bringing the peak down
- Run fewer things at once. Most of these kills happen while several heavy processes run in parallel: lower the concurrency of the task runner (Turborepo's
--concurrency,make -j), the number of test workers (Jest's--maxWorkers), or move a heavy check into its own job, which gets its own runner. - For Node.js, set the heap limit below the runner's memory with
NODE_OPTIONS=--max-old-space-size=...(in MB). A process that hits that limit fails with "JavaScript heap out of memory" and says so, instead of being killed without a word; a limit above the runner's memory only moves the kill. - A tool built for an older toolchain can use far more memory on a newer one. golangci-lint v1.64.8 grows without limit under Go 1.26 (Go 1.24 leaves the runner images).
- Adding a swap file lets the step survive a short peak at the cost of speed, and it uses disk space (No space left on device).
- If the work needs it, use a larger runner with more memory.
Telling it apart
- Exit code 143 is 128 + 15, SIGTERM: the job was cancelled, ran out of time or lost its runner (shutdown signal, "The operation was canceled", maximum execution time).
- Exit code 134 with "FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory": Node.js hit its own heap limit, not the runner's memory.
- "No space left on device": the disk, not memory (what to remove).
See failed jobs from IntelliJ IDEA
Pipeline Inbox for GitHub Actions Workflows, a plugin by Lesstep for JetBrains IDEs 2024.1 or later, lists the runs of all your repositories in an IDE tool window, with their jobs and steps, so the step that was killed stands out, and your current branch's runs are in the status bar. Reading is free; re-running failed jobs, cancelling, running workflows and reviewing deployments are Pro (US$1.50 a month, with a 30-day trial).
Get it on JetBrains Marketplace
GitHub and GitHub Actions are trademarks of GitHub, Inc.; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with, sponsored or endorsed by GitHub, Inc. or JetBrains.
More: The runner has received a shutdown signal · No space left on device · GitHub Actions plugins for IntelliJ IDEA compared · 日本語