What CreateContainerConfigError means
CreateContainerConfigError is reported by the kubelet when it cannot assemble
the runtime configuration for a container. The Pod has already been scheduled to
a node, but the kubelet fails at the generate container configuration step —
before it ever asks the container runtime to create the container — because
something the Pod spec references cannot be resolved.
This is distinct from CreateContainerError, which fails one step later, at the
actual container-create call, for runtime reasons (duplicate container name, a
bad command, an unmountable volume). If the status is CreateContainerConfigError,
the problem is almost always a ConfigMap, Secret, or a specific key that the
spec asks for and the kubelet cannot find. The kubelet retries on each sync loop,
so the Pod stays stuck rather than entering a restart backoff.
Diagnose it
Start with the Pod status and the events the kubelet recorded. The describe
events name the exact object and key:
kubectl get pod <pod> -n <namespace>
kubectl describe pod <pod> -n <namespace>
Read the Events section at the bottom. You will see one of these shapes:
Warning Failed kubelet Error: configmap "app-config" not found
# or
Warning Failed kubelet Error: couldn't find key DATABASE_URL in Secret default/app-secrets
# or
Warning Failed kubelet Error: secret "app-secrets" not found
The first line tells you whether the missing thing is an object (the whole ConfigMap/Secret) or a key inside an object that does exist. That split decides which fix below applies. Confirm what is actually present in the namespace:
kubectl get configmap -n <namespace>
kubectl get secret -n <namespace>
kubectl get configmap app-config -n <namespace> -o yaml
Mechanism 1 — ConfigMap or Secret does not exist in the namespace
The most common cause. The event reads configmap "..." not found or
secret "..." not found. The object was never created, or it lives in a
different namespace. ConfigMaps and Secrets are namespaced, and a Pod can only
reference objects in its own namespace — a ConfigMap in default is invisible to
a Pod in payments. The Kubernetes docs are explicit that a ConfigMap "must
exist before a Pod that consumes it is created, unless the reference is marked as
optional" (Configure a Pod to Use a ConfigMap).
Diagnose: compare the name in the event against kubectl get configmap/secret -n <namespace>.
If it is absent there but present elsewhere, it is a namespace mismatch.
Fix: create the object in the Pod's own namespace, or correct the name in the
Pod spec. To copy one from another namespace:
kubectl get configmap app-config -n default -o yaml \
| sed 's/namespace: default/namespace: payments/' \
| kubectl apply -n payments -f -
Mechanism 2 — the object exists but a referenced key is missing
The event reads couldn't find key DATABASE_URL in ConfigMap/Secret .... The
ConfigMap or Secret is present, but the specific key named under
valueFrom.configMapKeyRef.key or valueFrom.secretKeyRef.key is misspelled or
absent. The docs note that referencing "a key in the ConfigMap that does not
exist" fails Pod start just like a missing object does
(Configure a Pod to Use a ConfigMap).
Diagnose: dump the object and compare its keys against the spec.
kubectl get configmap app-config -n <namespace> -o jsonpath='{.data}'
kubectl get secret app-secrets -n <namespace> -o jsonpath='{.data}' # keys only
Fix: add the missing key to the object, or correct the key: in the Pod spec to
match an existing key. Secret keys are base64-encoded values, but the key names
are plain text and must match exactly.
Mechanism 3 — Secret rotated or recreated with a different key set
A common operational variant of Mechanism 2: an external secrets controller, a
rotation job, or a kubectl create secret --dry-run | apply re-created the Secret
with a renamed or dropped key. The object exists and looks healthy, but the key
the Deployment pins no longer exists.
Diagnose: check the object's age and managed-by labels, then diff its keys against
the Deployment's secretKeyRef entries.
kubectl get secret app-secrets -n <namespace> -o jsonpath='{.metadata.creationTimestamp}'
kubectl get deploy <deploy> -n <namespace> -o jsonpath='{range .spec.template.spec.containers[*].env[*]}{.valueFrom.secretKeyRef.key}{"\n"}{end}'
Fix: restore the expected key in the Secret source of truth (your secrets manager or manifest), or update the Deployment to the new key name. Re-apply, then let the kubelet retry.
Mechanism 4 — GitOps drift (Deployment synced, ConfigMap/Secret not)
The Deployment was applied but the ConfigMap/Secret manifest was not — a partial apply, a Kustomize/Helm template that did not render the ConfigMap, or an ArgoCD sync that excluded it. The reference points at an object that the cluster never received.
Diagnose: confirm the object is missing (Mechanism 1), then check whether your GitOps tool believes it is synced.
kubectl get configmap <name> -n <namespace> # not found
argocd app get <app> # is the ConfigMap in the resource tree?
Fix: ensure the ConfigMap/Secret manifest is part of the same application/release as the Deployment and re-sync. A missing-apply is a source-of-truth problem, not a cluster problem — patching the cluster by hand will drift back on the next sync.
Mechanism 5 — deliberately tolerate a missing reference with optional
This is the adjacent concept that decides the outcome. If a reference is truly
not required — an environment-specific override, a feature flag that only exists
in prod — mark it optional: true. The kubelet then skips the missing object or
key instead of failing, and the Pod starts. The docs state you "can mark a
reference to a ConfigMap as optional" on both configMapKeyRef and the envFrom
configMapRef/secretRef forms
(Configure a Pod to Use a ConfigMap).
env:
- name: PROXY_URL
valueFrom:
configMapKeyRef:
name: env-overrides
key: proxy_url
optional: true # Pod starts even if the key/object is absent
envFrom:
- secretRef:
name: extra-secrets
optional: true
Use optional: true only for values the app can run without. For database URLs,
credentials, and mandatory parameters, leave it off (the default,
optional: false) so a missing reference fails loudly at deploy time instead of
turning into a hard-to-trace runtime bug.
Mechanism 6 — envFrom silently skips invalid key names (a false trail)
A subtle diagnostic trap. When you load a whole ConfigMap with envFrom, keys
that are not valid environment-variable names (for example 1badkey, or names
with /) are silently skipped rather than failing the Pod — the docs confirm
these keys "will be skipped" but an event is recorded
(Configure a Pod to Use a ConfigMap).
This does not by itself cause CreateContainerConfigError, but it explains why an
app comes up "healthy" yet missing a variable you expected, which can look like a
config error during triage.
Diagnose: check kubectl describe pod for an InvalidVariableNames warning event
listing the skipped keys.
Fix: rename the offending key to alphanumeric-plus -_., or reference it
explicitly with valueFrom.configMapKeyRef and assign a valid name: for the
env var. Per the docs, ConfigMap data keys must consist of alphanumeric
characters, -, _, or .
(ConfigMap).
Fix it — quick path
- Read the
Eventsfromkubectl describe podand copy the exact object name and key it reports as missing. - Decide object-missing (Mechanism 1) vs key-missing (Mechanism 2/3) from the event text.
- Confirm what exists in the Pod's namespace:
kubectl get configmap/secret -n <namespace>. - Create or correct the ConfigMap/Secret in the right namespace, fix the
configMapKeyRef/secretKeyRefname, or — only for non-essential values — mark the referenceoptional: true. - If GitOps-managed, fix the manifest in source and re-sync rather than patching the cluster directly.
- Wait up to ~60s for the kubelet to retry, or
kubectl delete pod <pod> -n <namespace>and let its controller recreate it.
How Intellira diagnoses this
Intellira reads the Pod's status reason and the kubelet Events directly through
the Kubernetes MCP server, then extracts the named ConfigMap/Secret and key from
the event message. It checks whether the failure is an object-not-found or a
key-not-found, cross-checks the named object against the resources actually
present in the same namespace, and — when the workload is GitOps-managed —
against the ArgoCD application's resource tree to tell you whether the reference is
a typo, a missing apply, or a namespace mismatch. The result is one causality
chain from "Pod stuck" to the precise reference to fix.
Sources
- Configure a Pod to Use a ConfigMap — Kubernetes
- ConfigMap — Kubernetes
- Secrets — Kubernetes
- CreateContainerConfigError and CreateContainerError — Sysdig
By Intellira Engineering. AI-assisted draft, reviewed by the Intellira engineering team; claims cited inline; last verified 2026-06-02.