How to Fix a Stuck Kubernetes Job

A Kubernetes Job stuck at 0 completions means its pods keep failing. The fix is two steps: read the pod logs to find why, then fix the manifest and delete + recreate the Job - because you cannot re-apply a changed pod template.

Kubernetes Engineerkuberneteskubectljobs

Why the Job is stuck

kubectl get jobs shows 0/1 completions. The Job controller keeps spawning pods, each one fails, and after backoffLimit retries the Job stops trying. The Job itself stays in the namespace showing the failure count - it does not clean itself up.

The cause is always in the pod logs. Read them first.

Step 1: find the failing pod and read its logs

# See completion count and failure count
kubectl get jobs

# List the pods the Job created (they may be in Error/Completed state)
kubectl get pods -l job-name=migrate

# Read what the container actually printed
kubectl logs -l job-name=migrate

The output points directly at the problem. A typo in command: produces a classic:

sh: ehco: not found

That single line tells you ehco is not a real command - it should be echo.

Step 2: fix the manifest

Open job.yaml and correct the command in the container spec:

spec:
  template:
    spec:
      containers:
      - name: migrate
        image: busybox:1.36
        command: ["sh", "-c", "echo 'migration complete'"]

Save the file. Do not kubectl apply it yet.

Step 3: delete the old Job, then recreate it

Job pod templates are immutable - Kubernetes rejects any attempt to change spec.template on an existing Job. You must delete the old Job first:

# Delete the stuck Job (waits for full removal)
kubectl delete job migrate

# Apply the fixed manifest
kubectl apply -f job.yaml

# Wait for the Job to complete
kubectl wait --for=condition=complete job/migrate --timeout=90s

After a successful run, kubectl get jobs shows 1/1 completions.

Why immutable templates matter

Kubernetes freezes a Job's pod template at creation time by design - it prevents the spec from changing under in-flight pods. The rejection message from a naive re-apply is:

The Job "migrate" is invalid: spec.template: Invalid value:
... field is immutable

This trips up operators who are used to kubectl apply updating Deployments on the fly. For Jobs (and CronJobs), the pattern is always: delete, then recreate. For CronJobs the controller handles this automatically on the next scheduled run - but a one-off Job needs the manual delete cycle.

The investigation checklist

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

Why is my Kubernetes Job stuck at 0 completions?

The Job's pods are failing. Read the logs with kubectl logs -l job-name=<name> to find the error - a bad command, missing file, or failed script. After backoffLimit failures the Job stops retrying and stays stuck.

Can I update a Kubernetes Job's pod template with kubectl apply?

No - a Job's pod template is immutable. Kubernetes rejects changes to spec.template on an existing Job. You must delete the Job first, fix the manifest, then recreate it with kubectl apply.

How do I read logs from a failed Kubernetes Job pod?

Use kubectl logs -l job-name=<name> to query by the label the Job controller applies to every pod it creates. If the pod already exited, add --previous to see the last run's output.

Keep learning

Fix a Kubernetes CrashLoopBackOffKubernetes projectHeal a Kubernetes Service With No EndpointsKubernetes projectFix a Kubernetes ImagePullBackOffKubernetes projectKubernetes roadmapStep by step to hiredKubernetes interview questionsSTAR answersAll Kubernetes projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →