Skip to content
Latchkey LogoLatchkey home

Docker push to ECR repository does not exist

Docker push to ECR repository does not exist means the registry accepted your credentials and then found nothing to push into, so create the repository first: Amazon ECR only makes one during a push when a repository creation template matches the name. The login is not the problem, which is why the fix is in your infrastructure rather than in your workflow credentials.

Diagram of the three ways an ECR repository gets created and what a push does without one
ECR creates a repository during a push only when a creation template matches the name. Otherwise the repository has to exist before the push starts.

What this error means

The login step passes, the layers start uploading or fail immediately, and the push ends on a "name unknown" error that names the repository and the registry id. The registry id is your AWS account number and the host carries the region, so the message is telling you exactly where it looked. It is deterministic: the same push fails the same way until a repository exists at that name, in that account, in that region. We have not reproduced this one on a runner, because a real push needs AWS credentials and an account we are not going to put in a public page, so the log below is the shape ECR prints rather than a recorded run. Everything else on this page is quoted from the AWS documentation, read on 2026-09-20.

The shape ECR prints on push (illustrative, not a recorded run)
The push refers to repository [123456789012.dkr.ecr.us-east-1.amazonaws.com/api]
name unknown: The repository with name 'api' does not exist in the registry with id '123456789012'

ECR does not create the repository for you, with one exception

The AWS documentation is direct about it: "The Amazon ECR repository must exist before you push the image, or you must have a repository creation template defined." The template is the exception, and it is narrow. A template carries a repository name prefix and a list of actions it applies for, which can include CREATE_ON_PUSH, and only a push whose repository name matches that prefix gets a repository made for it.

Without a matching template, AWS says plainly that "Amazon ECR will not create a repository with default settings" for an image push. That is a deliberate difference from a pull-through cache, where ECR does fall back to default settings when no template matches.

How the repository gets thereWhat it costs you
A create-repository call in the pipelineOne idempotent step, plus an IAM action the push policy does not include
Terraform or another infrastructure toolA plan and apply before the first deploy, and one place that owns settings
A repository creation template with CREATE_ON_PUSHA prefix to match, and a creation role when the template sets tags or KMS
NothingThis error, on the first push of every new service

Common causes

The repository was never created

The first deploy of a new service, or a service renamed in the workflow and nowhere else. Everything up to the push works, which is what makes it confusing: the credentials are valid, the image built, and the registry is real. Only the repository is missing.

The push is pointed at the wrong region or account

A copied workflow keeps a region, a role change moves the account, or a matrix deploys to two regions from one reference. The repository exists, just not where the push looked. The registry id in the error is the account it actually reached.

A creation template exists and its prefix does not match

A template set up for prod covers repositories beginning with prod/ and nothing else, so a push to staging/api gets no repository and this error. In our experience this is the surprising one, because the team knows create-on-push is configured and does not know it is scoped by prefix.

The job can push but cannot create

A pipeline written to create the repository on demand fails at the create call instead, with an access error rather than this one, when its role carries only the documented push permissions. The AWS push policy grants the layer and image actions and the authorization token, not repository creation.

How to fix it

Create the repository before the first push

  1. Create it once with aws ecr create-repository in the correct region, or in your infrastructure tool.
  2. Confirm it from the job with aws ecr describe-repositories and the name.
  3. Keep the name in one variable that both the tag and the create call read.
Terminal
aws ecr create-repository --repository-name api --region us-east-1
aws ecr describe-repositories --repository-names api --region us-east-1 \
  --query "repositories[0].repositoryUri" --output text

Add a repository creation template if you want create-on-push

Define the template with the prefix your services use and CREATE_ON_PUSH among its applied-for actions, so the first push of a new service makes the repository with the settings you chose. Use ROOT as the prefix to cover every repository that has no more specific template.

Terminal
aws ecr create-repository-creation-template \
  --prefix prod \
  --applied-for CREATE_ON_PUSH \
  --image-tag-mutability MUTABLE \
  --region us-east-1

Give the job the permission the fix needs

The documented push policy covers uploading layers and putting an image. A job that creates repositories needs ecr:CreateRepository as well, and a template that applies tags or a KMS key needs a repository creation role for ECR to assume. Grant the create action on a narrow resource rather than on every repository in the account.

IAM policy
{
  "Effect": "Allow",
  "Action": ["ecr:CreateRepository", "ecr:DescribeRepositories"],
  "Resource": "arn:aws:ecr:us-east-1:123456789012:repository/*"
}

Fail early instead of failing at the push

A push is the end of a build, so this error costs the whole build before it appears. Check the repository at the start of the job, when the failure costs seconds, and say which repository, account and region were expected.

.github/workflows/deploy.yml
- name: Repository must exist
  run: |
    aws ecr describe-repositories --repository-names "$REPO" --region "$AWS_REGION" \
      || { echo "::error::no ECR repository $REPO in $AWS_REGION"; exit 1; }

The registry URL says which account and which region it looked in

The host is <account>.dkr.ecr.<region> followed by amazonaws.com, so a push carries the account and the region inside the image reference. A repository that exists in us-east-1 is genuinely absent from eu-west-1, and a repository in the shared services account is absent from the account your workflow assumed a role into. Both read as "repository does not exist" because, from where the push landed, that is true.

In a GitHub Actions job using OIDC, the account in the reference and the account behind the role have to agree. Print the caller identity next to the reference once, and this whole class of confusion goes away.

.github/workflows/deploy.yml
- uses: aws-actions/configure-aws-credentials@v6
  with:
    role-to-assume: arn:aws:iam::123456789012:role/gha-push
    aws-region: us-east-1
- run: |
    aws sts get-caller-identity --query Account --output text
    echo "pushing to: $IMAGE"

Create it in the job, or own it in infrastructure

A guard step in the pipeline is the fastest fix and it is idempotent: describe the repository, and create it only when the describe fails. It needs an IAM action the standard push policy does not carry, which is the part teams miss. The AWS push policy lists the layer and image actions plus ecr:GetAuthorizationToken, and nothing that creates a repository.

If your repositories carry lifecycle policies, tags, scanning settings or KMS keys, put them in Terraform instead and let the pipeline fail loudly when one is missing. A repository created by a push inherits whatever the template says, and a repository created ad hoc by a CLI call inherits the account defaults, which is how registries end up with images nobody ever expires.

.github/workflows/deploy.yml
REPO=api
aws ecr describe-repositories --repository-names "$REPO" --region us-east-1 \
  --query "repositories[0].repositoryUri" --output text \
  || aws ecr create-repository --repository-name "$REPO" --region us-east-1 \
       --image-scanning-configuration scanOnPush=true

What the runner does about it

Nothing, and no runner should. This failure is a statement about your registry, not about the machine the job ran on: the push reached ECR, authenticated, and asked for a repository that is not there. A retry on a bigger runner, a different image or a warmer cache changes none of it.

It is also the reason this page carries no reproduction. Our harness runs failures on a Latchkey latchkey-small runner and records the log, and a real ECR push needs AWS credentials, so there is nothing here we could honestly record. The pages in this cluster that did reproduce say so in their own log captions.

How to prevent it

  • Provision ECR repositories as infrastructure, so a first deploy never races a create call.
  • Keep the account and region in one place the workflow reads, not in a copied string.
  • If you rely on create-on-push, check the template prefix covers every namespace you push to.
  • Check the repository exists at the start of the job rather than at the push.

Frequently asked questions

Does ECR create a repository automatically when you push?
Only when a repository creation template matches the name and applies for create-on-push. AWS states that the repository must exist before you push, or a template must be defined, and that without a matching template ECR will not create a repository with default settings. The long-running request to relax this is aws/containers-roadmap#1299.
Why does the push say the repository does not exist when I can see it in the console?
Because the console is showing you a different account or region from the one the push reached. The registry host encodes both: the account id is the first label and the region is the third. Compare the account in the error with aws sts get-caller-identity inside the same job.
What IAM permissions does a job need to create the repository itself?
More than the push policy grants. The documented push permissions are the layer upload actions, ecr:PutImage, ecr:BatchGetImage and ecr:GetAuthorizationToken; creating a repository needs ecr:CreateRepository too, and describing one needs ecr:DescribeRepositories. A template that sets tags or a KMS key also needs a repository creation role.
Should I create ECR repositories in Terraform or in the CI pipeline?
Terraform, when the repository carries settings you care about: lifecycle policy, scanning, encryption, tags. A pipeline create-repository call is fine for a sandbox and it quietly accepts account defaults, which is how images accumulate forever. Whichever you choose, check for the repository early so the failure is not a wasted build.

Related guides

References

Every merge pushes an image. Latchkey runs those jobs at $0.0025/min at 2 vCPU against $0.006 GitHub-hosted. Start free → 30-day trial · No credit card