Skip to content

Ollama’s “Llama Runner Process Has Terminated” Error

9 min read · updated August 11, 2026

Error: llama runner process has terminated: exit status 2, or exit status 0xc0000409, or a variant naming a signal. Whatever follows the colon, this message is Ollama telling you that the process it started died. The cause is in that process’s output, not in this line.

What the message is reporting

Ollama is a server that does not run models in its own process. When a request arrives for a model that is not loaded, it starts a separate runner — a llama.cpp-derived binary — and talks to it locally. If that child exits before or during the load, the server has nothing to forward to you except the fact of its death and its exit code. That is what this string is.

The practical consequence: the message is invariant across wildly different faults. Out of memory, an unsupported CPU instruction, a missing shared library, a corrupt GGUF, a driver crash and an assertion failure all produce the same sentence with a different number after it. Any advice that offers one fix for this string is guessing.

It also appears wrapped in an HTTP error when you hit the API rather than the CLI — 500 Internal Server Error: llama runner process has terminated — which is the same event seen through the API layer.

Reading the exit status

The number carries real information once you know which namespace it is in.

  • exit status 2 is the runner exiting after printing an error. This is the most common value and the most benign — it means the child failed cleanly and said why, in output you have not read yet.
  • exit status 127 on Linux and macOS is the shell and loader’s “command or shared library not found”. It points at a missing runtime library rather than at anything about the model; the missing-OpenMP-runtime page covers the usual instance.
  • exit status 132 is 128 + 4, SIGILL: an illegal instruction, meaning a binary compiled for CPU features this machine does not have. 134 is 128 + 6, SIGABRT, which is what an assertion failure looks like from outside. 139 is 128 + 11, SIGSEGV.
  • 0xc0000409 on Windows is STATUS_STACK_BUFFER_OVERRUN, which Windows also uses as the generic fast-fail code, so in practice it means the process aborted. 0xc0000135 is STATUS_DLL_NOT_FOUND — a missing DLL, most often a runtime or a GPU library the build expects. 0xc0000005 is an access violation.

Two of these are immediately actionable without any log at all: a DLL not found is an install problem, and SIGILL is a CPU-compatibility problem. Everything else needs the log.

Where the real error is

The runner’s stderr goes to the Ollama server’s log, which is not where the CLI is printing. Ollama’s own troubleshooting documentation gives the locations per platform:

# Linux, systemd
journalctl -u ollama --no-pager | tail -n 200

# macOS
tail -n 200 ~/.ollama/logs/server.log

# Windows: %LOCALAPPDATA%\Ollama\server.log (rotated as server-1.log, ...)
#   explorer %LOCALAPPDATA%\Ollama

# Docker
docker logs ollama --tail 200

Two things about that stderr are worth knowing before you go looking for it, because they explain why the log is so often disappointing. The server reads the runner’s output as the runner produces it, and what reaches the log is what had been flushed before the process died. A crash — a segfault, an abort, a hard fail-fast — kills the process without flushing buffered output, so the last and most relevant lines can be gone. A clean exit after an error message is the opposite case, which is why exit status 2 is the friendly one.

The second is that the server keeps only a bounded amount of it. Ollama holds a tail of the runner’s output to put into the error it returns, so a runner that printed a great deal before dying can push the actual cause out of the window, leaving you a tail of progress lines. Both problems have the same remedy: reproduce with the server in the foreground, where the child’s stderr goes to your terminal directly rather than through the server’s buffer.

Then raise the verbosity and reproduce. OLLAMA_DEBUG=1 makes the server log the runner’s command line, the memory it estimated, the layers it decided to offload and the child’s output. Stop the service, export the variable, and run ollama serve in a terminal so the output is in front of you:

sudo systemctl stop ollama
OLLAMA_DEBUG=1 ollama serve
# in another terminal:
ollama run llama3.2 "hi"
Ollama’s environment variables are added and retired between releases, and how you set them differs by platform — a systemd drop-in on Linux, launchctl setenv on macOS, the user environment on Windows. Check the current troubleshooting document for your version rather than assuming a variable still exists.

The causes, in order of frequency

  • Not enough memory for the requested configuration. The runner is killed or exits while allocating. The debug log shows the estimate it made against the memory it found; on Linux, a kernel OOM kill also appears in dmesg. Increasing the context length is the most common way people cross the line without realising, because the KV cache grows with it.
  • A GPU that initialises and then fails. Driver mismatches, a card without enough VRAM for the layers Ollama chose, and ROCm version mismatches on AMD all kill the child after it has started. Test by forcing CPU: OLLAMA_NUM_GPU=0 ollama serve, or by setting the layer count to zero for the model. If CPU works, it is the GPU path.
  • An unsupported CPU. Runners are built for baseline instruction sets; a very old or heavily virtualised CPU without the expected AVX support dies with SIGILL before printing anything useful.
  • A corrupt or partial model blob. If the download was interrupted, the runner fails on load. ollama rm and re-pull; a mismatched digest surfaces as a checksum failure instead when the corruption is caught earlier.
  • An assertion in the vendored llama.cpp. If the log contains a GGML_ASSERT line, that is your real error and the assertion tells you what broke. New model architectures against an older Ollama build are the usual source.

Isolating it from Ollama entirely

When the log is ambiguous, take Ollama out of the picture. Ollama stores model layers as content-addressed blobs; the GGUF is one of them, and you can point an upstream llama.cpp binary at it directly. The manifest under ~/.ollama/models/manifests/ names the digest of each layer, and the blob lives at ~/.ollama/models/blobs/sha256-<digest>.

Running that file with a current llama-cli gives you an unwrapped error message with real content in it. If upstream loads it fine and Ollama does not, the fault is in Ollama’s version or its layer-offload decision, and that is a useful thing to report. If upstream fails the same way, you now have the actual error and can stop reading about runner processes. The Ollama guide covers the model store layout in more detail.

One case deserves separating from all the others, because it produces no message at all: being killed rather than crashing. On Linux, when the machine runs out of memory the kernel chooses a process and sends it SIGKILL. The runner does not get to print anything, does not run any cleanup, and cannot flush a buffer, so the log ends mid-load with nothing wrong on the last line. That is a fundamentally different shape of evidence from a crash: an absence rather than an error.

It is easy to confirm, and worth confirming before you go looking for a model or driver fault that does not exist:

# the kernel records every kill it makes
dmesg -T | grep -i -e "out of memory" -e "killed process"
journalctl -k --since "10 min ago" | grep -i oom

# example line
#   Out of memory: Killed process 41233 (ollama_llama_se) total-vm:...

A hit there ends the investigation. The process name in the kernel message is the runner, not ollama itself, which is why people searching their logs for the parent find nothing. macOS has the same behaviour under a different name — the memory pressure mechanism terminates the process and the kernel records a jetsam event rather than an OOM one — and Docker adds a third variant, where a container memory limit rather than the host’s memory is what was exceeded. Check docker inspect for OOMKilled being true; that distinguishes a container limit you set from a machine that is genuinely full, and the fixes are unrelated.

The reason this matters for diagnosis is that a kill is a statement about the whole machine at that instant, not about the model. A model that loaded yesterday and is killed today, with nothing changed, means something else on the box grew. Reducing context length or offloading fewer layers will make the load fit again, but if the model itself was always within budget, the honest fix is elsewhere.