How to fix Failed to pull image: secret not found in Kubernetes
This error occurs when a pod references an imagePullSecret that doesn't exist in its namespace. Fix it by creating the secret in the correct namespace and ensuring the name matches the pod specification.
Quick fix
Fixes Failed to pull image: secret not found
# List secrets in the namespace
kubectl get secrets -n <YOUR_NAMESPACE>
# Get detailed info about the secret
kubectl get secret <SECRET_NAME> -n <YOUR_NAMESPACE> -o yaml
# Verify it's the correct type
kubectl get secret <SECRET_NAME> -n <YOUR_NAMESPACE> -o jsonpath='{.type}'
# Should output: kubernetes.io/dockerconfigjson- Verify the secret exists in the correct namespace
- Create the Docker registry secret
- Ensure pod specification references correct secret name
- Configure service account with imagePullSecrets
# List secrets in the namespacekubectl get secrets -n <YOUR_NAMESPACE># Get detailed info about the secretkubectl get secret <SECRET_NAME> -n <YOUR_NAMESPACE> -o yaml# Verify it's the correct typekubectl get secret <SECRET_NAME> -n <YOUR_NAMESPACE> -o jsonpath='{.type}'# Should output: kubernetes.io/dockerconfigjsonFailed to pull image: secret not found
What this error means
The "Failed to pull image: secret not found" error means Kubernetes tried to use an imagePullSecret referenced in your pod spec, but couldn't find a secret with that name in the pod's namespace. ImagePullSecrets in Kubernetes are namespace-scoped resources. A secret created in namespace A is completely invisible to pods in namespace B. When your pod specification references a secret name that either doesn't exist or exists in a different namespace, the kubelet cannot retrieve the credentials needed to authenticate with the container registry. This error often occurs during multi-namespace deployments where secrets were created in the default namespace but pods run in application-specific namespaces.
Typical symptoms
- Pod stuck in ImagePullBackOff status
- Events show FailedToRetrieveImagePullSecret reason
- Pods work in default namespace but fail in custom namespaces
- Works when pulling public images, fails with private registries
- Same deployment works in staging but fails in production namespace
Common causes
- Secret does not exist—never created or was deleted
- Secret created in different namespace than the pod (namespaces isolate secrets)
- Typo in secret name referenced in imagePullSecrets
- Wrong secret type (Opaque instead of kubernetes.io/dockerconfigjson)
- Secret deleted during cluster maintenance or namespace cleanup
How to fix "Failed to pull image: secret not found"
Check if the secret exists in the pod's namespace:
# List secrets in the namespace
kubectl get secrets -n <YOUR_NAMESPACE>
# Get detailed info about the secret
kubectl get secret <SECRET_NAME> -n <YOUR_NAMESPACE> -o yaml
# Verify it's the correct type
kubectl get secret <SECRET_NAME> -n <YOUR_NAMESPACE> -o jsonpath='{.type}'
# Should output: kubernetes.io/dockerconfigjsonIf the secret doesn't exist, you'll see "Error from server (NotFound)".
Create the secret with proper credentials in the correct namespace:
kubectl create secret docker-registry <SECRET_NAME> \
--docker-server=<REGISTRY_URL> \
--docker-username=<USERNAME> \
--docker-password=<PASSWORD> \
--docker-email=<EMAIL> \
-n <YOUR_NAMESPACE>Example for Docker Hub:
kubectl create secret docker-registry dockerhub-creds \
--docker-server=docker.io \
--docker-username=myusername \
--docker-password=mytoken \
--docker-email=user@example.com \
-n productionVerify creation:
kubectl get secret dockerhub-creds -n productionVerify your pod spec uses the exact secret name:
apiVersion: v1
kind: Pod
metadata:
name: private-image-pod
namespace: production
spec:
containers:
- name: app
image: private-registry.io/myapp:latest
imagePullSecrets:
- name: dockerhub-creds # Must match secret name exactlyCheck the current pod's imagePullSecrets:
kubectl get pod <POD_NAME> -n <NAMESPACE> -o jsonpath='{.spec.imagePullSecrets}'Add the secret to the service account so all pods using it inherit the credentials:
kubectl patch serviceaccount default \
-n <YOUR_NAMESPACE> \
-p '{"imagePullSecrets": [{"name": "<SECRET_NAME>"}]}'Or use YAML:
apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: production
imagePullSecrets:
- name: dockerhub-credsVerify:
kubectl get serviceaccount default -n production -o yamlIf you need the same secret in multiple namespaces:
# Export from source namespace and apply to target
kubectl get secret my-secret -n source-namespace -o yaml | \
sed 's/namespace: source-namespace/namespace: target-namespace/' | \
kubectl apply -f -Script to replicate to all namespaces:
#!/bin/bash
SECRET_NAME="my-secret"
SOURCE_NS="default"
for ns in $(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}'); do
if [ "$ns" != "$SOURCE_NS" ]; then
kubectl get secret "$SECRET_NAME" -n "$SOURCE_NS" -o yaml | \
sed "s/namespace: $SOURCE_NS/namespace: $ns/" | \
kubectl apply -f -
fi
doneComprehensive debugging:
# View pod events for exact error
kubectl describe pod <POD_NAME> -n <NAMESPACE>
# Verify secret contains valid credentials
kubectl get secret <SECRET_NAME> -n <NAMESPACE> \
-o jsonpath='{.data.\.dockerconfigjson}' | base64 -d | jq .
# Check if serviceaccount has the secret
kubectl get serviceaccount <SA_NAME> -n <NAMESPACE> -o yaml | grep -A 5 imagePullSecrets
# Test with a debug pod
kubectl run debug-pod --image=busybox -n <NAMESPACE> \
--rm -it --restart=Never \
--overrides='{"spec":{"imagePullSecrets":[{"name":"<SECRET_NAME>"}]}}'Advanced notes
Cross-Namespace Secret Limitation: Kubernetes does NOT support cross-namespace secret references. This is a fundamental security constraint—the kubelet cannot check RBAC for secrets in other namespaces.
Solutions for Multi-Namespace Environments:
- Manual replication: Create identical secrets in each namespace
- kubernetes-reflector: Auto-syncs secrets across namespaces with annotation-based rules
- Banzai Cloud IMPS: Distributes imagePullSecrets based on namespace/pod labels
- registry-creds: Propagates a single secret to all namespaces cluster-wide
Service Account vs Direct Pod Specification: Using service accounts is recommended—it centralizes management and automatically applies to all pods using that account. Direct pod specification requires updating every deployment when credentials change.
System Namespaces: Pods in kube-system, kube-public, and operator namespaces also cannot access secrets from other namespaces. System-level operators need their own credentials if pulling from private registries.
Frequently asked questions
- What does "Failed to pull image: secret not found" mean?
- The "Failed to pull image: secret not found" error means Kubernetes tried to use an imagePullSecret referenced in your pod spec, but couldn't find a secret with that name in the pod's namespace. ImagePullSecrets in Kubernetes are namespace-scoped resources. A secret created in namespace A is completely invisible to pods in namespace B.
- How do I fix "Failed to pull image: secret not found"?
- This error occurs when a pod references an imagePullSecret that doesn't exist in its namespace. Fix it by creating the secret in the correct namespace and ensuring the name matches the pod specification.
- What causes "Failed to pull image: secret not found"?
- Secret does not exist—never created or was deleted Secret created in different namespace than the pod (namespaces isolate secrets) Typo in secret name referenced in imagePullSecrets
- Is the "Failed to pull image: secret not found" error serious?
- Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.
Official resources & further reading
- 📚Kubernetes Official Documentation
- 📖Docs: Private registry images(Official Docs)
- 💬SO: imagePullSecret Kubernetes(Stack Overflow)
- 🐙