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

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 (not Pending, not ImagePullBackOff).
  • kubectl describe pod shows configmap "<name>" not found or couldn'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 -f of 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: true so 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 default object is visible elsewhere.
  • Validate manifests in CI (e.g., kubeconform plus a check that every configMapKeyRef/secretKeyRef resolves) before merge. More patterns are in the Kubernetes & Helm guides.
  • Prefer envFrom with explicit, reviewed ConfigMaps over scattered per-key valueFrom references 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:

  1. envFrom/configMapRef/secretRef names an object that does not exist.
  2. The object exists, but a configMapKeyRef/secretKeyRef key is absent.
  3. The object lives in the wrong namespace (references are namespace-local).
  4. The Secret/ConfigMap is created after the pod — an ordering race.
  5. A genuinely optional reference is missing optional: true.
  6. 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.

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.