🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

AWS ECR Push Denied: no basic auth credentials — Fix

Getting 'no basic auth credentials' or 'denied: Your authorization token has expired' when pushing to AWS ECR? Here are the exact commands to fix authentication for Docker, GitHub Actions, and Kubernetes.

Shubham4 min read
Share:Tweet

ECR authentication errors are common and confusing because the error message is vague and the token expires every 12 hours. Here are all the ways this breaks and how to fix each.

Error: "no basic auth credentials"

docker push 123456789.dkr.ecr.ap-south-1.amazonaws.com/myapp:v1.0
Error response from daemon: no basic auth credentials

Cause: Docker has no ECR credentials. You need to authenticate first.

Fix:

bash
# Get your account ID
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
AWS_REGION=ap-south-1
 
# Login to ECR — this command pipes the password directly to docker login
aws ecr get-login-password --region $AWS_REGION | \
  docker login --username AWS --password-stdin \
  $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com
 
# Now push
docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/myapp:v1.0

The old aws ecr get-login command is deprecated — always use get-login-password piped to docker login.

Error: "Your authorization token has expired"

denied: Your authorization token has expired. Reauthenticate and try again.

Cause: ECR tokens are valid for 12 hours. After that, you must re-authenticate.

Fix: Run the same aws ecr get-login-password command again. There is no way to extend the token — it always expires at 12 hours.

For CI/CD, add the auth command at the start of every pipeline run instead of caching credentials.

Error: "Repository does not exist"

name unknown: The repository with name 'myapp' does not exist in the registry with id '123456789'

Cause: ECR repositories must be created before pushing. Unlike Docker Hub, ECR does not auto-create repositories.

Fix:

bash
# Create the repository first
aws ecr create-repository \
  --repository-name myapp \
  --region ap-south-1 \
  --image-scanning-configuration scanOnPush=true
 
# Enable immutable tags (recommended for production)
aws ecr put-image-tag-mutability \
  --repository-name myapp \
  --image-tag-mutability IMMUTABLE \
  --region ap-south-1

Error: "Access Denied" (IAM Permissions)

denied: User: arn:aws:iam::123456789:user/ci-user is not authorized to perform: ecr:GetAuthorizationToken

Cause: The IAM user/role does not have ECR permissions.

Fix — minimum IAM policy for pushing:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecr:GetAuthorizationToken"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchGetImage",
        "ecr:PutImage",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload",
        "ecr:DescribeRepositories",
        "ecr:CreateRepository"
      ],
      "Resource": "arn:aws:ecr:ap-south-1:123456789:repository/myapp"
    }
  ]
}

Note: ecr:GetAuthorizationToken requires Resource: "*" — it cannot be scoped to a specific repository.

Fix for GitHub Actions

Do NOT store AWS access keys in GitHub Secrets for production. Use OIDC instead.

With OIDC (correct approach):

yaml
jobs:
  push-to-ecr:
    runs-on: ubuntu-latest
    permissions:
      id-token: write   # Required for OIDC
      contents: read
 
    steps:
      - uses: actions/checkout@v4
 
      - name: Configure AWS credentials via OIDC
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/github-actions-ecr
          aws-region: ap-south-1
 
      - name: Login to ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2
 
      - name: Build and push
        env:
          REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $REGISTRY/myapp:$IMAGE_TAG .
          docker push $REGISTRY/myapp:$IMAGE_TAG

IAM Trust Policy for GitHub Actions OIDC:

json
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "Federated": "arn:aws:iam::123456789:oidc-provider/token.actions.githubusercontent.com"
    },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
      "StringEquals": {
        "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
      },
      "StringLike": {
        "token.actions.githubusercontent.com:sub": "repo:your-org/your-repo:*"
      }
    }
  }]
}

Fix for Kubernetes (Pulling from ECR)

ECR tokens expire, which breaks Kubernetes image pulls after 12 hours. The proper fix is an external secrets operator or IAM roles for service accounts.

Quick fix — manually update imagePullSecret:

bash
kubectl create secret docker-registry ecr-creds \
  --docker-server=123456789.dkr.ecr.ap-south-1.amazonaws.com \
  --docker-username=AWS \
  --docker-password=$(aws ecr get-login-password --region ap-south-1) \
  -n production

Production fix — ECR credential helper on nodes:

Install amazon-ecr-credential-helper on nodes. Nodes with an IAM instance profile that includes ECR permissions will automatically refresh tokens — no imagePullSecret needed.

bash
# For EKS: attach an IAM policy to the node group role
# AmazonEC2ContainerRegistryReadOnly is sufficient for pulling
 
# For self-managed nodes:
apt-get install amazon-ecr-credential-helper
# Then add to /etc/docker/config.json:
echo '{"credHelpers": {"123456789.dkr.ecr.ap-south-1.amazonaws.com": "ecr-login"}}' > /etc/docker/config.json

Quick Reference

bash
# Re-authenticate (run this when you see auth errors)
aws ecr get-login-password --region ap-south-1 | \
  docker login --username AWS --password-stdin \
  $(aws sts get-caller-identity --query Account --output text).dkr.ecr.ap-south-1.amazonaws.com
 
# Check current auth status
cat ~/.docker/config.json | grep ecr
 
# Create missing repository
aws ecr create-repository --repository-name myapp --region ap-south-1
 
# Check your IAM permissions
aws iam simulate-principal-policy \
  --policy-source-arn $(aws sts get-caller-identity --query Arn --output text) \
  --action-names ecr:GetAuthorizationToken \
  --resource-arns "*"

More AWS ECR issues? Read our ECR image lifecycle policy setup and ECR image scanning with Trivy.

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments