How to fix Failed to pull image: unauthorized in Kubernetes

KubernetesINTERMEDIATEHIGHUpdated Dec 7, 2025· 238 views

This error occurs when Kubernetes cannot authenticate with a container registry to pull a private image. Fix it by creating imagePullSecrets with valid registry credentials and referencing them in your pod spec or service account.

Quick fix

Fixes Failed to pull image: unauthorized

kubectl create secret docker-registry regcred \
  --docker-server=<REGISTRY_URL> \
  --docker-username=<USERNAME> \
  --docker-password=<PASSWORD> \
  --docker-email=<EMAIL> \
  --namespace=<YOUR_NAMESPACE>
  1. Create a Docker registry secret
  2. Add imagePullSecrets to your pod specification
  3. Configure service account for automatic secret inheritance
  4. Verify secret contents and format
kubernetes — error
kubectl create secret docker-registry regcred \
--docker-server=<REGISTRY_URL> \
--docker-username=<USERNAME> \
--docker-password=<PASSWORD> \
--docker-email=<EMAIL> \
--namespace=<YOUR_NAMESPACE>
Failed to pull image: unauthorized

What this error means

The "Failed to pull image: unauthorized" error indicates that the kubelet on your Kubernetes node attempted to pull an image from a container registry but failed authentication. This manifests as ErrImagePull initially, then ImagePullBackOff as Kubernetes retries with exponential backoff. Container registries require authentication for private images. When a pod references a private image, Kubernetes needs valid credentials stored in an imagePullSecret. Without proper credentials—or with expired/incorrect ones—the registry rejects the pull request with an "unauthorized" response. This error commonly occurs with Docker Hub private repositories, AWS ECR, Google GCR, Azure ACR, and self-hosted registries. Each has specific authentication requirements and token expiration policies that must be managed.

Typical symptoms

  • Pod stuck in ImagePullBackOff status
  • kubectl describe pod shows "Failed to pull image" with "unauthorized" message
  • Image pulls work locally with docker login but fail in Kubernetes
  • Pods in one namespace work but fail in another namespace
  • ECR image pulls fail after 12 hours (token expiration)

Common causes

  1. Missing imagePullSecrets in pod specification or service account
  2. Credentials in the secret are expired, incorrect, or lack required permissions
  3. Secret exists in a different namespace than the pod (namespaces isolate secrets)
  4. Secret type is Opaque instead of kubernetes.io/dockerconfigjson
  5. Service account not configured with imagePullSecrets for automatic inheritance

How to fix "Failed to pull image: unauthorized"

1Create a Docker registry secret

Create a secret with your registry credentials:

bash
kubectl create secret docker-registry regcred \
  --docker-server=<REGISTRY_URL> \
  --docker-username=<USERNAME> \
  --docker-password=<PASSWORD> \
  --docker-email=<EMAIL> \
  --namespace=<YOUR_NAMESPACE>

Common registry servers:
- Docker Hub: https://index.docker.io/v1/
- AWS ECR: <ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com
- Google GCR: gcr.io
- Azure ACR: <REGISTRY_NAME>.azurecr.io

Verify the secret was created:

bash
kubectl get secret regcred -n <YOUR_NAMESPACE>
2Add imagePullSecrets to your pod specification

Reference the secret in your pod or deployment:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    spec:
      imagePullSecrets:
      - name: regcred
      containers:
      - name: app
        image: myregistry.azurecr.io/myapp:latest

Apply and verify:

bash
kubectl apply -f deployment.yaml
kubectl get pod <POD_NAME> -o jsonpath='{.spec.imagePullSecrets}'
3Configure service account for automatic secret inheritance

Instead of adding imagePullSecrets to every pod, patch the service account:

bash
kubectl patch serviceaccount default \
  -n <YOUR_NAMESPACE> \
  -p '{"imagePullSecrets": [{"name": "regcred"}]}'

Verify the patch:

bash
kubectl get serviceaccount default -n <YOUR_NAMESPACE> -o yaml

All new pods using the default service account will automatically inherit the imagePullSecrets.

4Verify secret contents and format

Decode and inspect the secret to ensure correct structure:

bash
kubectl get secret regcred \
  --output="jsonpath={.data.\.dockerconfigjson}" \
  | base64 --decode

Expected output structure:

json
{
  "auths": {
    "myregistry.azurecr.io": {
      "username": "myuser",
      "password": "mypassword",
      "auth": "base64-encoded-credentials"
    }
  }
}

Check secret type (must be kubernetes.io/dockerconfigjson):

bash
kubectl get secret regcred -o jsonpath='{.type}'
5Diagnose using kubectl describe

Get detailed error messages from the pod:

bash
kubectl describe pod <POD_NAME>

Look for events showing:
- "Failed to pull image": Check if secret exists and credentials are correct
- "Repository does not exist": Verify image name/tag is correct
- "No pull access": Missing or invalid imagePullSecret

Save full details for analysis:

bash
kubectl describe pod <POD_NAME> > pod-debug.txt
kubectl get pod <POD_NAME> -o yaml > pod-spec.yaml
6Create secret from existing Docker config

If you've already run docker login locally:

bash
kubectl create secret generic regcred \
  --from-file=.dockerconfigjson=~/.docker/config.json \
  --type=kubernetes.io/dockerconfigjson

Generate YAML for version control:

bash
kubectl create secret docker-registry regcred \
  --docker-server=<REGISTRY> \
  --docker-username=<USER> \
  --docker-password=<PASS> \
  --dry-run=client \
  -o yaml > secret.yaml

Advanced notes

AWS ECR Token Expiration: ECR tokens expire after 12 hours. For long-running clusters, set up a CronJob to refresh credentials every 6 hours, or use tools like k8s-ecr-login-renew.

GCR with Workload Identity: For GKE, use Workload Identity instead of manual secrets—it handles authentication automatically without credential rotation.

Azure ACR with Managed Identity: On AKS, enable Managed Identity and assign the ACRPull role to avoid manual secret management entirely.

Docker Hub Rate Limits: Authenticated pulls get 200 pulls/6 hours vs 100 for anonymous. Use a personal access token, not your password.

Namespace Isolation: Secrets cannot be shared across namespaces. Either create the secret in each namespace or use a controller like kubernetes-reflector to auto-sync secrets.

Frequently asked questions

What does "Failed to pull image: unauthorized" mean?
The "Failed to pull image: unauthorized" error indicates that the kubelet on your Kubernetes node attempted to pull an image from a container registry but failed authentication. This manifests as ErrImagePull initially, then ImagePullBackOff as Kubernetes retries with exponential backoff. Container registries require authentication for private images.
How do I fix "Failed to pull image: unauthorized"?
This error occurs when Kubernetes cannot authenticate with a container registry to pull a private image. Fix it by creating imagePullSecrets with valid registry credentials and referencing them in your pod spec or service account.
What causes "Failed to pull image: unauthorized"?
Missing imagePullSecrets in pod specification or service account Credentials in the secret are expired, incorrect, or lack required permissions Secret exists in a different namespace than the pod (namespaces isolate secrets)
Is the "Failed to pull image: unauthorized" 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