Kubernetes Error Guide: 'CreateContainerConfigError' Missing ConfigMap or Secret
Fix the Kubernetes CreateContainerConfigError: diagnose missing ConfigMaps and Secrets, absent keys, wrong namespaces, ordering races, and bad envFrom/valueFrom references.
- #kubernetes
- #troubleshooting
- #errors
- #configmap
Overview
CreateContainerConfigError means the kubelet successfully pulled the image but could not assemble the container’s configuration, because something the pod spec references — a ConfigMap, a Secret, or a specific key inside one — does not exist. The pod is scheduled and the image is present, but the container never starts.
You will see this in kubectl get pods:
NAME READY STATUS RESTARTS AGE
api-6c8f9d7b54-q9w2r 0/1 CreateContainerConfigError 0 47s
And the underlying reason in the pod’s events:
Error: configmap "api-config" not found
Or, when the object exists but a referenced key does not:
Error: couldn't find key DATABASE_URL in ConfigMap shop/api-config
It occurs whenever a container references config via envFrom, env.valueFrom.configMapKeyRef, env.valueFrom.secretKeyRef, or a projected/volume mount, and that source is missing at container-create time. Unlike an image pull error, the scheduling and image are fine — only the config wiring is broken.
Symptoms
- Pod status is
CreateContainerConfigError(notPending, notImagePullBackOff). kubectl describe podshowsconfigmap "<name>" not foundorcouldn't find key <KEY>.- The container never reaches
Running; restarts stay at 0 because it never started. - The Deployment rolls out one bad pod and the rollout stalls.
kubectl get pods -n shop
NAME READY STATUS RESTARTS AGE
api-6c8f9d7b54-q9w2r 0/1 CreateContainerConfigError 0 47s
api-5b7c8d6f43-h2k8n 1/1 Running 0 3h
kubectl describe pod api-6c8f9d7b54-q9w2r -n shop | sed -n '/Events/,$p'
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Pulled 12s (x4 over 47s) kubelet Container image "registry.example.com/api:1.8.2" already present on machine
Warning Failed 12s (x4 over 47s) kubelet Error: configmap "api-config" not found
Common Root Causes
1. envFrom references a ConfigMap/Secret that does not exist
The pod uses envFrom.configMapRef (or secretRef) naming an object that was never created (or was deleted/renamed).
kubectl get configmap -n shop
NAME DATA AGE
app-config 6 3h
kube-root-ca.crt 1 3h
The pod references api-config, but only app-config exists — a rename that was not applied to the Deployment.
2. A referenced key is missing inside an existing object
The ConfigMap/Secret exists, but configMapKeyRef/secretKeyRef names a key that is not present.
kubectl get configmap app-config -n shop -o jsonpath='{.data}' | tr ',' '\n'
{"APP_PORT":"8080"
"LOG_LEVEL":"info"
"FEATURE_FLAGS":"beta"}
The container asks for DATABASE_URL via configMapKeyRef, but the ConfigMap has no such key, producing couldn't find key DATABASE_URL.
3. The object is in the wrong namespace
ConfigMaps and Secrets are namespaced; a pod can only reference one in its own namespace. The object exists, but in default instead of shop.
kubectl get secret db-credentials --all-namespaces
NAMESPACE NAME TYPE DATA AGE
default db-credentials Opaque 2 5h
The pod runs in shop, so the shop-namespaced lookup fails even though the secret exists elsewhere.
4. The Secret/ConfigMap is created after the pod (ordering race)
In a fresh deploy, the pod can be created before its Secret (e.g., an external-secrets sync, a Helm hook, or a separate kubectl apply step has not run yet).
kubectl get secret api-tls -n shop
Error from server (NotFound): secrets "api-tls" not found
The pod is in CreateContainerConfigError now; once the secret lands, the kubelet retries and the container starts — but only if nothing else is wrong.
5. Missing optional: true for an intentionally absent source
If a reference is genuinely optional but the spec omits optional: true, Kubernetes treats the missing source as a hard error instead of skipping it.
kubectl get pod api-6c8f9d7b54-q9w2r -n shop -o jsonpath='{.spec.containers[0].envFrom}'; echo
[{"configMapRef":{"name":"feature-overrides"}}]
feature-overrides is meant to be present only in staging; without "optional":true on the ref, its absence in prod breaks container creation.
6. Typo in the env name, key, or valueFrom reference
A simple typo in the ConfigMap/Secret name or the key string sends the lookup to something that does not exist.
kubectl get pod api-6c8f9d7b54-q9w2r -n shop -o jsonpath='{range .spec.containers[0].env[*]}{.name}{" <- "}{.valueFrom.secretKeyRef.name}{"/"}{.valueFrom.secretKeyRef.key}{"\n"}{end}'
DB_PASSWORD <- db-credentials/postgres-pasword
The key postgres-pasword is a typo for postgres-password, so the lookup yields couldn't find key.
Diagnostic Workflow
Step 1: Confirm the status and read the exact error
kubectl get pod <POD> -n <NS>
kubectl describe pod <POD> -n <NS> | sed -n '/Events/,$p'
The event message tells you whether it is a missing object (... not found) or a missing key (couldn't find key ...).
Step 2: Identify every config source the container references
kubectl get pod <POD> -n <NS> -o yaml | grep -nE 'configMapRef|secretRef|configMapKeyRef|secretKeyRef|name:|key:|optional'
List the exact names and keys the spec expects.
Step 3: Verify the objects exist in the pod’s namespace
kubectl get configmap -n <NS>
kubectl get secret -n <NS>
A name in the spec that is not in this list is your missing object. If you suspect a namespace mistake, run with --all-namespaces.
Step 4: Verify the specific keys exist
kubectl get configmap <NAME> -n <NS> -o jsonpath='{.data}' | tr ',' '\n'
kubectl get secret <NAME> -n <NS> -o jsonpath='{.data}' | tr ',' '\n'
Compare the key names against the configMapKeyRef/secretKeyRef from Step 2 — watch for typos and case.
Step 5: Fix the source, then let the kubelet retry
# create the missing ConfigMap/Secret, or fix the reference, then:
kubectl rollout restart deploy/<DEPLOY> -n <NS>
kubectl get pods -n <NS> -w
The kubelet retries CreateContainerConfigError automatically, but a rollout restart guarantees a clean pod once the source is corrected.
Example Root Cause Analysis
A new api Deployment in namespace shop rolls out one pod stuck in CreateContainerConfigError.
kubectl describe pod shows the image is present and the failure is config:
Normal Pulled kubelet Container image "registry.example.com/api:1.8.2" already present on machine
Warning Failed kubelet Error: couldn't find key DATABASE_URL in ConfigMap shop/app-config
So the object exists; a key does not. Listing the spec’s references:
kubectl get pod api-6c8f9d7b54-q9w2r -n shop -o jsonpath='{range .spec.containers[0].env[*]}{.name}{" <- "}{.valueFrom.configMapKeyRef.name}{"/"}{.valueFrom.configMapKeyRef.key}{"\n"}{end}'
DATABASE_URL <- app-config/DATABASE_URL
The container wants the key DATABASE_URL from app-config. Checking what the ConfigMap actually contains:
kubectl get configmap app-config -n shop -o jsonpath='{.data}' | tr ',' '\n'
{"APP_PORT":"8080"
"LOG_LEVEL":"info"
"DB_URL":"postgres://db:5432/shop"}
The connection string is stored under DB_URL, but the Deployment references DATABASE_URL. The key name drifted between the config and the manifest.
Fix: align the names — either add a DATABASE_URL key to the ConfigMap or point the configMapKeyRef.key at DB_URL — then restart the rollout:
kubectl patch configmap app-config -n shop --type merge \
-p '{"data":{"DATABASE_URL":"postgres://db:5432/shop"}}'
kubectl rollout restart deploy/api -n shop
The kubelet finds the key, the container is configured, and the pod reaches Running.
Prevention Best Practices
- Apply ConfigMaps and Secrets before the workloads that reference them (Helm hooks, Kustomize ordering, or
kubectl apply -fof config first) to avoid ordering races. - Keep config object names and keys under version control alongside the Deployment so a rename in one place forces the matching change in the other.
- Mark genuinely optional references with
optional: trueso an absent source is skipped rather than fatal across environments. - Remember that ConfigMaps and Secrets are namespaced — a pod can only reference ones in its own namespace; never assume a
defaultobject is visible elsewhere. - Validate manifests in CI (e.g.,
kubeconformplus a check that everyconfigMapKeyRef/secretKeyRefresolves) before merge. More patterns are in the Kubernetes & Helm guides. - Prefer
envFromwith explicit, reviewed ConfigMaps over scattered per-keyvalueFromreferences to reduce typo surface.
Quick Command Reference
# Confirm status and the exact failure message
kubectl get pod <POD> -n <NS>
kubectl describe pod <POD> -n <NS> | sed -n '/Events/,$p'
# List every config source the container references
kubectl get pod <POD> -n <NS> -o yaml | grep -nE 'configMapRef|secretRef|configMapKeyRef|secretKeyRef|name:|key:|optional'
# Do the objects exist (in this namespace)?
kubectl get configmap -n <NS>
kubectl get secret -n <NS>
kubectl get configmap <NAME> --all-namespaces
# Do the specific keys exist?
kubectl get configmap <NAME> -n <NS> -o jsonpath='{.data}' | tr ',' '\n'
kubectl get secret <NAME> -n <NS> -o jsonpath='{.data}' | tr ',' '\n'
# Fix the source, then force a clean pod
kubectl rollout restart deploy/<DEPLOY> -n <NS>
kubectl get pods -n <NS> -w
Conclusion
CreateContainerConfigError means the image is fine but the kubelet could not build the container’s config because a referenced ConfigMap, Secret, or key is missing. The usual root causes:
envFrom/configMapRef/secretRefnames an object that does not exist.- The object exists, but a
configMapKeyRef/secretKeyRefkey is absent. - The object lives in the wrong namespace (references are namespace-local).
- The Secret/ConfigMap is created after the pod — an ordering race.
- A genuinely optional reference is missing
optional: true. - A typo in the object name or key string sends the lookup nowhere.
Read the event message first: ... not found points to a missing object, couldn't find key ... points to a missing key — then verify names, keys, and namespace against the spec.
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.