Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Kubernetes & Helm By James Joyner IV · · 9 min read

Kubernetes Error Guide: 'Init Container Failed' — Unblock Init:Error

Fix an init container that exits non-zero in Kubernetes: read Init:Error and Init:CrashLoopBackOff, decode exit codes, and check init logs, dependencies, and mounts.

  • #kubernetes
  • #troubleshooting
  • #errors
  • #init-containers

Overview

Init containers run to completion, one at a time and in order, before any of a pod’s main containers are allowed to start. When an init container exits with a non-zero code, Kubernetes does not proceed to the app containers — it reports the pod as Init:Error (or Init:CrashLoopBackOff once the kubelet starts backing off) and holds there. The main container never boots, so nothing serves traffic even though the image and app themselves may be perfectly fine.

You will see this in the pod status column:

NAME                        READY   STATUS                  RESTARTS   AGE
api-6f8c4d7b9e-r3m8t        0/1     Init:CrashLoopBackOff   4          3m20s

The Init: prefix is the tell — the failure is in the initialization phase, not the app. Common causes are a bad command or missing binary in the init container, a dependency (database, config service, migration target) that is not ready when init runs, a bad volume mount the init step needs, or a script that simply exits non-zero. Because init containers respect the pod’s restartPolicy, a failing one loops just like a crashing app container, but the status keeps the Init: prefix so you know where to look.

Symptoms

  • Pod status shows Init:Error, Init:0/1, or Init:CrashLoopBackOff and never reaches Running.
  • READY is 0/1 and the main container has status Waiting with reason PodInitializing.
  • kubectl describe pod lists the init container under Init Containers with a non-zero Exit Code.
  • Logs from the init container (via -c <init>) contain the failure message.
kubectl get pods -l app=api
NAME                        READY   STATUS                  RESTARTS   AGE
api-6f8c4d7b9e-r3m8t        0/1     Init:CrashLoopBackOff   4          3m20s
kubectl describe pod api-6f8c4d7b9e-r3m8t | grep -A8 'Init Containers'
Init Containers:
  wait-for-db:
    State:          Terminated
      Reason:       Error
      Exit Code:    1
    Restart Count:  4

Common Root Causes

1. The init container waits on a dependency that is not ready

The classic init-container job is to block until a database, cache, or upstream service is reachable. If that dependency never comes up (wrong host, wrong port, service not deployed), the init step times out or fails and the pod is stuck.

kubectl logs api-6f8c4d7b9e-r3m8t -c wait-for-db
waiting for db.prod.svc.cluster.local:5432 ...
nc: bad address 'db.prod.svc.cluster.local'
timeout waiting for dependency, exiting 1

Here the Service name is wrong or the DB is not deployed. Fix the address or deploy the dependency, and the init step completes.

2. Bad command, missing binary, or wrong image

If the init container’s command/args points at a binary that does not exist in its image, the container exits immediately with a non-zero code — often exit 127 (command not found) or 126 (not executable).

kubectl logs api-6f8c4d7b9e-r3m8t -c run-migrations --previous
exec /usr/local/bin/migrate: no such file or directory

The migrate binary is not in the image, or the path is wrong. Use an image that contains the tool, or correct the command path.

3. Migration or setup script exits non-zero

An init container that runs a schema migration, seed, or config-render step fails if that command returns an error — a duplicate migration, a syntax error in a template, or a bad credential.

kubectl logs api-6f8c4d7b9e-r3m8t -c run-migrations
applying migration 0007_add_index.sql
ERROR: relation "orders" does not exist (SQLSTATE 42P01)
migration failed, exit status 1

The migration depends on a table that is not there yet. Fix the migration ordering or the target schema, then re-roll.

4. Bad volume mount or missing config the init step needs

Init containers often read from a mounted ConfigMap, Secret, or volume. If that mount is missing or the referenced object does not exist, the init step fails when it tries to read it.

kubectl describe pod api-6f8c4d7b9e-r3m8t | grep -A4 Events
  Warning  Failed   25s   kubelet   Error: configmap "bootstrap-config" not found

A missing ConfigMap surfaces as CreateContainerConfigError on the init container. Create the object or mark the reference optional: true.

5. Insufficient permissions in the init step

An init container running under a restrictive securityContext may be unable to write to a shared emptyDir, chown a path, or open a device — a frequent pattern where init exists specifically to prepare a volume for the main container.

kubectl logs api-6f8c4d7b9e-r3m8t -c fix-perms
chown: changing ownership of '/data': Operation not permitted
exit status 1

The init step needs the right runAsUser/fsGroup or capabilities to prepare the path. Adjust the securityContext.

Diagnostic Workflow

Step 1: Confirm it is an init-phase failure

kubectl get pod <POD> -n <NS> -o wide

An Init: prefix in the status confirms the failure is in an init container, not the app.

Step 2: Identify which init container failed

kubectl describe pod <POD> -n <NS>

The Init Containers block lists each one with its State, Reason, and Exit Code. Init containers run in order, so the first non-Terminated (Completed) one is the culprit.

Step 3: Read that init container’s logs

kubectl logs <POD> -n <NS> -c <INIT_CONTAINER>
kubectl logs <POD> -n <NS> -c <INIT_CONTAINER> --previous

You must pass -c <name> — plain kubectl logs <pod> targets the main container, which has not started. Use --previous if the init container has already restarted.

Step 4: Decode the exit code and events

kubectl get pod <POD> -n <NS> \
  -o jsonpath='{.status.initContainerStatuses[0].lastState.terminated}'
kubectl get events -n <NS> --field-selector involvedObject.name=<POD> --sort-by='.lastTimestamp'

Map the code: 1/2 app/script error, 126 not executable, 127 command not found, 137 OOM/SIGKILL. Events reveal missing ConfigMaps/Secrets as CreateContainerConfigError.

Step 5: Verify the init command, mounts, and dependency

kubectl get pod <POD> -n <NS> -o jsonpath='{.spec.initContainers[0].command}{"\n"}'
kubectl get pod <POD> -n <NS> -o jsonpath='{.spec.initContainers[0].volumeMounts}{"\n"}'
kubectl get svc,configmap,secret -n <NS>

Confirm the command exists in the image, the mounts reference real objects, and the dependency the init step waits on is actually deployed.

Example Root Cause Analysis

A payments-api rollout hangs; every pod sits in Init:CrashLoopBackOff.

kubectl get pods -l app=payments-api -n prod
NAME                              READY   STATUS                  RESTARTS   AGE
payments-api-7b9d5c6f8a-9k4wq     0/1     Init:CrashLoopBackOff   5          4m02s

Describe shows the failing init container:

kubectl describe pod payments-api-7b9d5c6f8a-9k4wq -n prod | grep -A6 'Init Containers'
Init Containers:
  wait-for-db:
    State:          Waiting  (CrashLoopBackOff)
    Last State:     Terminated
      Reason:       Error
      Exit Code:    1

Reading its logs:

kubectl logs payments-api-7b9d5c6f8a-9k4wq -n prod -c wait-for-db
waiting for postgres:5432 ...
nc: bad address 'postgres'
timeout after 60s, giving up

The init step targets the bare host postgres, but the database Service in this namespace is payments-db. The name never resolves, init times out, and the pod loops.

Checking the actual Service:

kubectl get svc -n prod | grep db
payments-db   ClusterIP   10.96.14.22   <none>   5432/TCP   9d

Fix: point the init container at the correct Service name and re-roll:

kubectl set env deployment/payments-api -n prod DB_HOST=payments-db.prod.svc.cluster.local
kubectl rollout restart deployment payments-api -n prod

The init container connects, completes, and the main container finally starts.

Prevention Best Practices

  • Always pass -c <init-name> when debugging — the default kubectl logs targets the main container, which never started, and hides the real error.
  • Give dependency-wait init containers a bounded, logged timeout so a stuck pod tells you what it was waiting on instead of hanging silently.
  • Reference dependencies by their fully qualified Service DNS name (svc.<ns>.svc.cluster.local) to avoid namespace-resolution surprises.
  • Test init-container images and commands in CI the same way you test app images — a missing binary is a leading cause of 127/126 init failures.
  • Make migrations and setup scripts idempotent so a retried init container does not fail on already-applied work.
  • Confirm every ConfigMap, Secret, and volume the init step mounts exists in the namespace before rollout. See more in Kubernetes & Helm guides.

Quick Command Reference

# Confirm an init-phase failure
kubectl get pod <POD> -n <NS> -o wide

# Which init container failed, with exit code
kubectl describe pod <POD> -n <NS>

# The failing init container's logs (must pass -c)
kubectl logs <POD> -n <NS> -c <INIT_CONTAINER>
kubectl logs <POD> -n <NS> -c <INIT_CONTAINER> --previous

# Terminated state and exit code
kubectl get pod <POD> -n <NS> \
  -o jsonpath='{.status.initContainerStatuses[0].lastState.terminated}'

# Events (missing ConfigMap/Secret show here)
kubectl get events -n <NS> --field-selector involvedObject.name=<POD> --sort-by='.lastTimestamp'

# Init command, mounts, and available dependencies
kubectl get pod <POD> -n <NS> -o jsonpath='{.spec.initContainers[0].command}{"\n"}'
kubectl get svc,configmap,secret -n <NS>

# Re-roll after a fix
kubectl rollout restart deployment <DEPLOY> -n <NS>

Conclusion

An Init:Error / Init:CrashLoopBackOff pod is blocked in its initialization phase — one init container exited non-zero, so the main containers are never started. The usual root causes:

  1. The init container waits on a dependency (DB, cache, service) that is unreachable.
  2. A bad command or missing binary makes the init container exit immediately (127/126).
  3. A migration or setup script returns a non-zero exit code.
  4. A missing ConfigMap/Secret or bad volume mount the init step needs (CreateContainerConfigError).
  5. Insufficient permissions stop the init step from preparing a shared volume.

Start by identifying which init container failed in kubectl describe pod, then read its logs with -c <name> — those two steps identify almost every init failure. For quick triage, the free incident assistant can turn an init describe dump into the likely root cause.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.