Skip to content
Intellira
Kuberneteshigh severity

CreateContainerConfigError

Why a Pod is stuck in CreateContainerConfigError and how to fix the missing ConfigMap, Secret, or key reference behind it.

Written by Intellira Engineering, Editorial team

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

  1. Read the Events from kubectl describe pod and copy the exact object name and key it reports as missing.
  2. Decide object-missing (Mechanism 1) vs key-missing (Mechanism 2/3) from the event text.
  3. Confirm what exists in the Pod's namespace: kubectl get configmap/secret -n <namespace>.
  4. Create or correct the ConfigMap/Secret in the right namespace, fix the configMapKeyRef/secretKeyRef name, or — only for non-essential values — mark the reference optional: true.
  5. If GitOps-managed, fix the manifest in source and re-sync rather than patching the cluster directly.
  6. 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

By Intellira Engineering. AI-assisted draft, reviewed by the Intellira engineering team; claims cited inline; last verified 2026-06-02.

Frequently asked questions

Is CreateContainerConfigError the same as CrashLoopBackOff?
No. CrashLoopBackOff means the container started and then exited repeatedly. CreateContainerConfigError happens earlier — the kubelet cannot even build the container configuration because a referenced ConfigMap, Secret, or key is missing, so the container never starts.
How is it different from CreateContainerError?
CreateContainerConfigError fails at the configuration-generation step, before the container runtime is asked to create anything — almost always a missing/wrong ConfigMap, Secret, or key. CreateContainerError fails later, at the actual container-create step, for runtime reasons like a duplicate container name, a bad command, or a mount that cannot be set up.
Why does the Pod not back off and retry like CrashLoopBackOff?
The kubelet keeps retrying container creation on its sync loop, but because the failure is a configuration lookup rather than a process crash, there is no exponential restart backoff. The Pod simply remains stuck until the referenced object and key exist.
Does fixing the ConfigMap automatically restart the Pod?
Usually yes — the kubelet retries on its sync loop, so creating the missing ConfigMap or Secret in the right namespace typically lets the Pod proceed without a manual delete. If it does not pick up within a minute, delete the Pod and let the controller recreate it.

Related errors

Find the root cause of CreateContainerConfigError on your stack

Connect read-only and Intellira correlates the change behind it across Bitbucket, Jenkins, ArgoCD and Kubernetes — with the evidence to prove it.