Exit code 143: terminated by SIGTERM (signal 15)
Exit code 143 means the process was terminated by SIGTERM (signal 15), because 143 = 128 + 15 under the convention that a process killed by signal N exits with 128 + N. SIGTERM is a polite request to stop that a process can catch and handle for a graceful shutdown, unlike SIGKILL. In scheduled jobs, exit 143 usually means something asked the job to stop — a deploy, a scale-down, a job timeout, or a container being shut down.
What sends SIGTERM to a scheduled job?
- A container or pod shutdown: Kubernetes and Docker send SIGTERM first (then SIGKILL after a grace period) when stopping a container — during a deploy, a rollout, an eviction, or a scale-down.
- A job timeout: a runner that enforces a maximum runtime (a CI job, a Kubernetes Job with activeDeadlineSeconds, a timeout wrapper) sends SIGTERM when the deadline passes.
- An operator or supervisor: systemctl stop, a process manager restarting the service, or an operator running kill (without -9) all send SIGTERM.
Is exit 143 a failure or an intended stop?
It depends on who sent the signal and why. If a deploy or a routine scale-down stopped the job, 143 is expected and not an error. If the job was killed because it ran past a timeout, that is a real problem — the work didn't finish. Look at what happened at the same time: a deploy in your CI/CD log, a rollout in kubectl get events, or a timeout message in the runner's output.
# Kubernetes: was it a deploy/eviction, or did it run past a deadline?
kubectl get events --sort-by=.lastTimestamp | tail -20
kubectl describe pod <pod> | grep -A3 "Last State" # Reason: Error, exit 143How do I make a job shut down cleanly on SIGTERM?
Because SIGTERM is catchable, a long-running job should trap it, stop taking new work, finish or checkpoint the current unit, and exit. That turns an abrupt 143 into a clean, resumable stop:
#!/usr/bin/env bash
cleanup() { echo "SIGTERM received, finishing current batch…"; save_checkpoint; exit 0; }
trap cleanup TERM
process_batches # long-running work that checks a stop flag between unitsHow do I get alerted only on the failure case?
You don't want an alert every time a deploy stops a job — you want one when a scheduled run didn't actually complete. Ping the monitor only after the job finishes its work, so a SIGTERM that interrupts it (a timeout, an unhandled shutdown mid-run) withholds the ping and alerts, while a run that completed before any shutdown pings normally.
run_the_job && curl -fsS -m 10 --retry 3 "https://ping.cronshield.com/<your-check-id>"Catch this failure automatically
The free tier gives you a heartbeat endpoint and an email alert when an expected ping doesn't arrive. Paid tiers add the log-aware diagnosis — the last log line and a likely cause in the alert. The heartbeat receiver ships in an upcoming release; see the plans to learn what each tier adds.
Frequently asked questions
- Is exit code 143 an error?
- Not necessarily. 143 = SIGTERM (signal 15), a polite stop. If a deploy, scale-down, or normal shutdown sent it, the job stopped intentionally and it's not an error. It IS a problem when SIGTERM came from a timeout and the job didn't finish its work.
- What's the difference between SIGTERM (143) and SIGKILL (137)?
- SIGTERM (143) is catchable — the process can trap it and shut down gracefully. SIGKILL (137) is uncatchable and immediate, giving no chance to clean up. Orchestrators typically send SIGTERM first and escalate to SIGKILL only if the process doesn't exit within a grace period.
Primary sources
- GNU Bash Manual — Exit Status (128 + N for signal N) — verified 2026-07-04
- Linux man-pages: signal(7) — SIGTERM is signal 15, catchable — verified 2026-07-04
- Kubernetes docs — pod termination sends SIGTERM then SIGKILL after the grace period — verified 2026-07-04