denied: requested access to the resource is denied - fix docker push and 'pull access denied, repository does not exist or may require docker login' (tested on Docker 28)

TL;DR

  • denied: requested access to the resource is denied is Docker Hub refusing a write. The repository you are pushing to is not yours, or you are not logged in. The image name decides the repository: docker push myapp:1.0 goes to docker.io/library/myapp, which belongs to Docker, so it is always denied.
  • The fix is three commands: docker tag myapp:1.0 YOUR_USERNAME/myapp:1.0, docker login (with an access token, not your password), docker push YOUR_USERNAME/myapp:1.0.
  • pull access denied for X, repository does not exist or may require 'docker login' is the same check on pull. It means the repository name is wrong or the repository is private; Docker Hub deliberately does not tell you which.
  • A stale login gives a different message: unauthorized: incorrect username or password. Run docker logout first; a leftover auth entry in ~/.docker/config.json is the usual cause after a password or token change.
  • Limits that bite: unauthenticated pulls are capped at 100 per 6 hours per IPv4 address, a Personal account gets 200, and repository names must be 2 to 255 lowercase characters.
  • Every output below is from Docker 28.0.4 on Ubuntu 24.04 with no Docker Hub login, captured on 2026-10-16, so every denial is the real anonymous behaviour.
  • Not your exact case? The closest post on this site is docker rename image.

I hit this error in 2021 pushing my first Spring Boot image, and the video above is the fix I found then. For this rewrite I reproduced every variant of the message on a clean machine with no Docker Hub credentials at all, so the outputs below are exactly what you see before you log in, and the working push goes to a registry I control.

Table of Content

  1. Every variant of the message and its cause
  2. Cause 1 - no username in the image name
  3. Cause 2 - someone else's namespace, or not logged in
  4. The pull-side twin - pull access denied
  5. Cause 3 - a stale or wrong login
  6. The fix - tag, login, push
  7. Docker Hub limits that look like access errors
  8. What broke when I ran this
  9. Conclusion

1. Every variant of the message and its cause

What you ranMessage (Docker 28.0.4)CauseFix
docker push myapp:1.0denied: requested access to the resource is deniedno namespace: the target is docker.io/library/myapptag as username/myapp
docker push other/myapp:1.0denied: requested access to the resource is deniednot logged in, or logged in as a different userdocker login as the owner
docker pull other/nothere:1.0pull access denied for other/nothere, repository does not exist or may require 'docker login'wrong name, or a private repositorycheck the name, log in
docker push ... with an old loginunauthorized: incorrect username or passwordstale auth in config.jsondocker logout, then docker login
docker login with a wrong tokenunauthorized: incorrect username or passwordbad credentialsnew access token
docker pull after many pullstoomanyrequests: You have reached your pull rate limit100 pulls per 6 hours anonymouslog in (200), or a paid plan

The first two produce an identical message because Docker Hub answers the same way whether the repository is Docker's own library/ namespace or another user's: you may not write here.


2. Cause 1 - no username in the image name

This is the one I hit first. An image built as myapp:1.0 has no namespace, and Docker fills in library/, which is reserved for official images:

1$ docker tag alpine:3.20 myapp:1.0
2$ docker push myapp:1.0
3The push refers to repository [docker.io/library/myapp]
408bc4e534116: Preparing
5denied: requested access to the resource is denied

The first line already tells you: [docker.io/library/myapp]. Nobody but Docker can push there, logged in or not. On Docker Hub your repository lives at docker.io/YOUR_USERNAME/myapp, so the image has to carry that name before the push. The docker push reference describes how the name maps to a registry and a repository.


3. Cause 2 - someone else's namespace, or not logged in

Tagging with a username is not enough if it is not your username, or you are not logged in:

1$ docker tag alpine:3.20 someone-else/myapp:1.0
2$ docker push someone-else/myapp:1.0
3The push refers to repository [docker.io/someone-else/myapp]
408bc4e534116: Preparing
5denied: requested access to the resource is denied

Same message. The usual ways to get here: a typo in your own username, an image tagged with a colleague's name from a copied command, or a CI job that never ran docker login because the secret was missing. Check which user you are with docker login (it prints the current user when already logged in) and compare it with the namespace in the tag.


4. The pull-side twin - pull access denied

On pull, the same permission check produces a longer message:

1$ docker pull someone-else/this-repo-does-not-exist:1.0
2Error response from daemon: pull access denied for someone-else/this-repo-does-not-exist, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
3
4$ docker pull minio/minio-typo:latest
5Error response from daemon: pull access denied for minio/minio-typo, repository does not exist or may require 'docker login': denied: requested access to the resource is denied

Docker Hub does not distinguish between "this repository does not exist" and "this repository is private and you may not see it", on purpose, so that private repository names cannot be guessed. Nine times out of ten it is a typo in the name or the tag (minio/minio-typo above). The remaining cases are a private repository you have not logged in for, or an image that was deleted. Verify the exact name on the repository's Docker Hub page before you suspect permissions.


5. Cause 3 - a stale or wrong login

After a password change or a revoked token, the saved login is still in ~/.docker/config.json and the message changes:

 1$ cat ~/.docker/config.json
 2{
 3  "auths": {
 4    "https://index.docker.io/v1/": {
 5      "auth": "c3RhbGUtdXNlcjpzdGFsZS10b2tlbg=="
 6    }
 7  }
 8}
 9
10$ docker push someone-else/myapp:1.0
11The push refers to repository [docker.io/someone-else/myapp]
1208bc4e534116: Preparing
13unauthorized: incorrect username or password

unauthorized means a credential was sent and rejected; denied means a credential was accepted (or none was sent) and the account has no rights. docker logout removes the entry:

1$ docker logout
2Removing login credentials for https://index.docker.io/v1/
3
4$ cat ~/.docker/config.json
5{
6	"auths": {}
7}

The auth value is only base64 of user:token, which is why the docker login reference recommends a credential helper, and why you should log out on shared machines.

docker logout before logging in with the right account


6. The fix - tag, login, push

With no Docker Hub credentials on my test machine, I used a local registry for the working push; the steps are identical for Docker Hub with localhost:5000 replaced by your username:

1$ docker tag alpine:3.20 localhost:5000/myapp:1.0
2$ docker push localhost:5000/myapp:1.0
3The push refers to repository [localhost:5000/myapp]
408bc4e534116: Preparing
508bc4e534116: Pushed
61.0: digest: sha256:6c2a9711b0a9f32b0239d9222eb1072309cf46c6431d319ae249186d811a987c size: 527
7
8$ curl -s http://localhost:5000/v2/_catalog
9{"repositories":["myapp"]}

For Docker Hub the three commands are:

1docker tag myapp:1.0 YOUR_USERNAME/myapp:1.0
2docker login -u YOUR_USERNAME            # paste an access token, not your password
3docker push YOUR_USERNAME/myapp:1.0

Create the token under Account settings, Personal access tokens, with read and write scope. Logging in with a wrong token fails before any push:

1$ echo not-a-real-token | docker login -u some-user --password-stdin
2Error response from daemon: Get "https://registry-1.docker.io/v2/": unauthorized: incorrect username or password

docker login with the account that owns the repository

A successful docker push after tagging with the username

The repository does not have to exist before the first push; Docker Hub creates it as public. Names must be 2 to 255 characters of lowercase letters, numbers, hyphens and underscores, and cannot be renamed later, per the create a repository page. If you need to change the name of an image before pushing, renaming a Docker image covers docker tag in detail, and the naming rules that produce invalid reference format are the ones that apply here.

One thing the three tags make visible: the same image ID under three names is three repositories, not one:

1$ docker images --filter reference='*myapp*' --filter reference='*/myapp*'
2REPOSITORY:TAG             IMAGE ID
3myapp:1.0                  bf8527eb54c3
4someone-else/myapp:1.0     bf8527eb54c3
5localhost:5000/myapp:1.0   bf8527eb54c3

7. Docker Hub limits that look like access errors

Two Docker Hub rules produce errors that people mistake for the permission problem. From the Docker Hub usage and limits page:

AccountPull rate limitPrivate repositories
Unauthenticated100 per 6 hours per IPv4 addressnot applicable
Personal (free, logged in)200 per 6 hoursup to 1
Pro, Team, Businessunlimitedunlimited

Hitting the pull limit gives toomanyrequests: You have reached your pull rate limit, not denied, but a CI runner behind a shared NAT address reaches 100 pulls surprisingly fast; logging in doubles the allowance. The remaining budget is in the response headers of any manifest request, and the window is given in seconds, 21600 seconds being the 6 hours:

1ratelimit-limit: 100;w=21600
2ratelimit-remaining: 20;w=21600

Those two lines are the example from the pull usage and limits page: 100 pulls per 21600 seconds, 20 left. And a Personal account gets 1 private repository: a push to a second private repository is refused with a quota message rather than the denial above.


8. What broke when I ran this

I ran all of this on a GitHub Actions runner on 2026-10-16 with an empty config.json, so there was no login to leak into the results.

1. The denial is identical for library/ and for a stranger's namespace. I expected Docker Hub to say something different for the reserved namespace. It does not, which is why the The push refers to repository [...] line matters more than the error line: it is the only place the target is spelled out.

2. A stale login is a different error, not the same one. With a fake auth entry the push said unauthorized: incorrect username or password, not denied. If you see unauthorized, the fix is docker logout and a fresh login; if you see denied, the fix is the tag or the account. The original version of this post treated them as one problem.

3. The local registry accepted the push in under a second with no login at all. That is the default for registry:2 on localhost, which is convenient for testing and dangerous anywhere else; a real private registry needs authentication in front of it.


9. Conclusion

denied: requested access to the resource is denied is Docker Hub telling you that the account you are using cannot write to the repository named in the tag. To summarise:

  1. Read the The push refers to repository [...] line; if it says library/, your image has no username.
  2. Tag the image as YOUR_USERNAME/repository:tag.
  3. docker logout, then docker login with an access token.
  4. docker push. The repository is created on first push.
  5. On pull, the same message almost always means a typo in the repository name.

If the push succeeds but the image then will not start, restarting a single container and the executable file not found error are the next two posts people land on.

Did this save you a debugging session? Stay in the loop -