Kubernetes
8 min readJuly 2, 2026Updated August 19, 2026

Fix Kubernetes Exit Code 137 (SIGKILL / OOMKilled)

AJ
Ajeet Yadav
Platform & Cloud Engineer
Fix Kubernetes Exit Code 137 (SIGKILL / OOMKilled)

Quick answer

Exit code 137 means your container was killed by SIGKILL — usually OOMKilled, but not always. Here's how to tell the difference and fix each root cause.

8 min read · Kubernetes

Fix Kubernetes Exit Code 137 (SIGKILL / OOMKilled)

You check a crashed pod and see this:

Last State:     Terminated
  Reason:       OOMKilled
  Exit Code:    137

Exit code 137 means the container was terminated by SIGKILL — a hard, non-negotiable kill. Most of the time that's the kernel OOM killer reclaiming memory, but it isn't the only cause, and treating every 137 as "just bump the memory limit" will burn you. Let's diagnose it properly.


What Exit Code 137 means

Container exit codes above 128 encode the signal that killed the process: the exit code is 128 + <signal number>. SIGKILL is signal 9, so 128 + 9 = 137.

The important thing about SIGKILL is that it can't be caught, blocked, or ignored. The process gets no chance to clean up — it's terminated instantly by the kernel. So 137 always means "something forcibly killed this container." Your job is to find out what sent the SIGKILL, because there are several culprits and they need different fixes.


Step 1: See the actual error

Start with describe, which shows the terminated state and reason:

bash
kubectl describe pod <pod-name>

Look at the Last State block and the Events section:

Last State:     Terminated
  Reason:       OOMKilled     # ← this is the smoking gun (or "Error")
  Exit Code:    137
  Started:      Wed, 02 Jul 2026 10:00:00
  Finished:     Wed, 02 Jul 2026 10:04:12

If Reason: OOMKilled, you have a memory problem (Cause 1 or 2). If Reason: Error with exit code 137 and no OOMKilled, the SIGKILL came from somewhere else — a probe or a shutdown timeout (Cause 3 or 4).

Then pull the cluster events and check the node:

bash
kubectl get events --sort-by=.lastTimestamp -n <namespace>
kubectl top pod <pod-name> -n <namespace>     # actual memory usage vs limit
kubectl describe node <node-name> | grep -A5 "Conditions"   # MemoryPressure?

Cause 1: Container exceeded its memory limit (OOMKilled)

The most common cause. Your container hit its own resources.limits.memory ceiling. The kernel cgroup enforces that limit and, when the process tries to allocate past it, the OOM killer terminates it with SIGKILL. Reason will read OOMKilled.

What you'll see: Reason: OOMKilled, exit code 137, and kubectl top pod showing usage pinned near the limit right before the kill.

Fix: Either the limit is genuinely too low, or the app has a memory leak. Right-size the limit based on real usage, and fix leaks rather than papering over them:

yaml
resources:
  requests:
    memory: "512Mi"
  limits:
    memory: "1Gi"    # raise to fit real working set, or fix the leak

If usage climbs steadily until the kill and never plateaus, that's a leak — raising the limit just delays the crash. For a deep dive on diagnosing and right-sizing memory, see the dedicated OOMKilled guide linked at the bottom.


Cause 2: Node-level memory pressure

Here the container gets killed even though it was under its own limit. When a node runs low on allocatable memory, the kubelet raises the MemoryPressure condition and starts evicting pods to reclaim resources. Pods with BestEffort QoS (no requests/limits) go first, then Burstable pods that exceed their requests. The killed process still exits 137.

What you'll see: kubectl describe node shows MemoryPressure True, and events show The node was low on resource: memory or Evicted. The pod's own usage may be well below its limit.

Fix: Give the scheduler accurate information and protect critical workloads:

yaml
resources:
  requests:
    memory: "512Mi"   # set requests so QoS is Burstable/Guaranteed, not BestEffort
  limits:
    memory: "512Mi"   # requests == limits → Guaranteed QoS, evicted last

Also add node capacity (or a bigger instance type), and consider priorityClassName on critical pods so they survive eviction. See the requests-and-limits guide below for how QoS classes map to eviction order.


Stuck on this in production?

We debug exactly this kind of issue for platform teams — usually in a single working session.

Talk to us

Cause 3: Liveness probe failing

A failing liveness probe makes the kubelet restart the container: it sends SIGTERM, waits for terminationGracePeriodSeconds, and if the process is still running, follows up with SIGKILL. That final SIGKILL surfaces as exit code 137 — with Reason: Error, not OOMKilled.

What you'll see: Events contain Liveness probe failed: ... shortly before the termination, and there's no OOMKilled reason or memory pressure.

Fix: Fix the probe, not the memory. If the app is slow to start, gate liveness behind a startupProbe; if the endpoint or port is wrong, correct it:

yaml
1startupProbe:
2  httpGet:
3    path: /health
4    port: 8080
5  failureThreshold: 30    # up to 5 minutes to boot
6  periodSeconds: 10
7
8livenessProbe:
9  httpGet:
10    path: /health
11    port: 8080
12  periodSeconds: 20
13  timeoutSeconds: 3       # don't fail just because a check was slow

Cause 4: App ignores SIGTERM during shutdown

When Kubernetes stops a pod (rollout, scale-down, node drain), it sends SIGTERM first and gives the process terminationGracePeriodSeconds (default 30s) to exit cleanly. If your app ignores SIGTERM — no signal handler, or a shutdown routine that hangs — the kubelet escalates to SIGKILL when the grace period expires. Result: exit code 137 on every deploy.

What you'll see: 137 exits correlate with rollouts or scale events, not with load or memory. No OOMKilled, no probe failures.

Fix: Handle SIGTERM for graceful shutdown so the process exits before the deadline. A minimal Node example:

javascript
process.on("SIGTERM", () => {
  server.close(() => process.exit(0));   // stop accepting, drain, exit
});

Give slow drains more room by raising the grace period:

yaml
spec:
  terminationGracePeriodSeconds: 60

Exit codes quick reference

Exit codeSignalMeaning
137SIGKILL (128 + 9)Force-killed — OOMKilled, node pressure, or post-grace-period kill
143SIGTERM (128 + 15)Graceful termination — app exited on shutdown signal
139SIGSEGV (128 + 11)Segmentation fault — memory access bug in the app
1—Generic application error (read the logs)
126—Command found but not executable (permissions)
127—Command not found (bad path or missing binary)

The one distinction that matters most: 137 is SIGKILL (forced), 143 is SIGTERM (graceful). A 143 on shutdown is usually normal. A 137 is not — something killed the process hard. And if you see a plain exit code 1, that's the application itself deciding to exit with an error, not the platform killing it — check the app logs, not the memory limits.


Frequently Asked Questions

Does exit code 137 always mean OOMKilled?

No. 137 means SIGKILL, and OOM is the most common source, but node memory pressure, a failing liveness probe, and an ignored SIGTERM during shutdown all produce 137 too. Check Reason in kubectl describe pod — OOMKilled confirms memory; Error points elsewhere.

How do I tell OOMKilled from node memory pressure?

If the container's own usage was pinned at its limit when it died, it hit its cgroup limit (Cause 1). If kubectl describe node shows MemoryPressure True and the pod was under its limit, the kubelet evicted it under node pressure (Cause 2). Set requests and limits to survive the latter.

What is the difference between exit code 137 and 143?

137 is 128 + 9 (SIGKILL) — a forced, uncatchable kill. 143 is 128 + 15 (SIGTERM) — the graceful stop signal the app can trap and handle. Seeing 143 on shutdown is normal; 137 means the process didn't stop in time or was killed outright.

Can I catch or handle SIGKILL to prevent 137?

No. SIGKILL cannot be caught, blocked, or ignored by design. What you can do is handle the SIGTERM that Kubernetes sends first, so your app shuts down cleanly before the grace period expires and the SIGKILL is never sent.

Why does my container get 137 only during deployments?

That pattern points to Cause 4: the app isn't handling SIGTERM, so it keeps running through terminationGracePeriodSeconds and gets SIGKILLed at the deadline. Add a SIGTERM handler for graceful shutdown and, if needed, raise the grace period.


See also

Still chasing a 137 that doesn't add up? Talk to us at Coding Protocols — we'll help you find the real killer and right-size your workloads so it stops happening.

Official References

Was this article helpful?

Be the first to rate this article

Related Topics

Kubernetes
Troubleshooting
OOMKilled
SIGKILL
DevOps

Found this useful? Share it.

Practice this

Related tools

Read Next