CreateContainerConfigError

K8s Pod CrashLoopBackOff: Fix CreateContainerConfigError

Your pod is stuck in CrashLoopBackOff because it's missing a referenced Secret. Create the Secret in the same namespace and the kubelet will retry on its own.

Quick answer: the kubelet can't find a Secret your pod references. Create the Secret in the same namespace with the exact name and keys, and the pod will recover on its own.

This error shows up as CreateContainerConfigError in kubectl get pods, and the status flips to CrashLoopBackOff because the kubelet keeps retrying and keeps failing. It's not a crash in your app — the container never even starts. The kubelet tries to build the container config (env vars, volume mounts, image pull secrets) before handing it to the runtime, and one of those references points to a Secret that doesn't exist in that namespace. Common triggers: someone copy-pasted a deployment manifest from staging into prod and forgot the Secret, a Helm chart references a Secret that's only created when a feature flag is on, or a CI pipeline deletes and recreates the Secret and the apply order is wrong. I've seen this a dozen times on EKS and GKE where the Secret lives in a different namespace than the workload.

Step 1 — Confirm it's really a missing Secret

Don't guess. Read the events.

kubectl describe pod <pod-name> -n <namespace>

You'll see something like:

Error: secret "my-app-secret" not found

That message names the missing Secret. Note it exactly — case-sensitive, including dashes. Kubernetes names are case-sensitive and people fat-finger this constantly.

Step 2 — Check if the Secret exists at all

kubectl get secret -n <namespace>
kubectl get secret <secret-name> -n <namespace> -o yaml

If it returns nothing, the Secret is gone. If it exists but the pod still fails, jump to Step 4 — you've got a key-level mismatch or a namespace mismatch, not a missing Secret.

Step 3 — Create the Secret in the right namespace

The secret must live in the same namespace as the pod. No cross-namespace references exist in vanilla Kubernetes. From a literal:

kubectl create secret generic my-app-secret \
  --from-literal=DB_PASSWORD='correct-horse-battery-staple' \
  --from-literal=API_KEY='abc123' \
  -n <namespace>

Or from a file:

kubectl create secret generic my-app-secret \
  --from-file=tls.crt --from-file=tls.key \
  -n <namespace>

Once it exists, the kubelet picks it up on the next retry — usually within 30–60 seconds. You don't need to delete the pod. Watch it with:

kubectl get pod <pod-name> -n <namespace> -w

Step 4 — Key mismatch, not name mismatch

If the Secret exists but you still get CreateContainerConfigError, the pod is asking for a key that isn't in the Secret. Compare the deployment's envFrom/valueFrom against the actual keys:

kubectl get secret <secret-name> -n <namespace> -o jsonpath='{.data}'

That prints the base64-encoded key list. If your manifest says secretKeyRef.key: db-password but the Secret has DB_PASSWORD, you get the same generic error. Keys are case-sensitive too. Fix the manifest, or add the missing key. Same deal for volume mounts pointing at a key that doesn't exist.

Alternative fixes

  • Namespace mismatch. Run kubectl get pods -A | grep my-app and compare the namespace column to where the Secret actually lives. Moving the Secret to the right namespace is the fix — don't try to make cross-namespace refs work, they don't.
  • Helm race condition. If it's a Helm chart, the Secret may be templated with a conditional (e.g. {{- if .Values.existingSecret }}). Either supply existingSecret or let the chart create it. helm template locally and read the output before you blame Kubernetes.
  • External Secrets Operator lag. If ESO or Vault injects the Secret, the pod can start before the Secret exists. Add a dependency or use an init container that waits for the Secret. Don't just crank the backoff — solve the ordering.
  • Image pull secret missing. Same error class. If your private-registry pull secret was deleted, the kubelet can't build the config. Recreate the docker-registry secret in the namespace.

Prevention

Secrets are the most common cause of this error because they're external state the manifest silently depends on. Two things help more than anything else: run a pre-deploy check that verifies every secretKeyRef resolves before you apply the workload, and put Secrets in the same Helm chart or Kustomize overlay as the deployment that consumes them so they move together. Also, turn off automountServiceAccountToken unless you need it — one less secret reference to break.

If you're on a recent version of Kubernetes (1.27+), enable the SecretManager style tooling with kubectl events to catch these earlier. But honestly, a five-line script that greps your manifests for secretKeyRef and checks kubectl get secret will save you more pain than any operator.

One more thing: don't delete the pod to "reset" the loop. It won't help — the kubelet retries anyway, and you lose the event history that would've told you which Secret was missing.

Related Errors in Server & Cloud
0X0000277F WSA_E_CANCELLED (0x0000277F) – WSALookupServiceEnd Conflict Fix 0XC00002C3 STATUS_MUTUAL_AUTHENTICATION_FAILED (0XC00002C3) Fix 0X000019F1 Fix ERROR_LOG_CONTAINER_OPEN_FAILED (0X000019F1) Fast 0X80100018 SCARD_P_SHUTDOWN (0X80100018) – Smart Card Server Dying

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.