docker: invalid reference format - Every Cause Reproduced with Docker 28 (repository name must be lowercase, spaces in -v, empty variables, wrong argument order) and the Fix for Each
TL;DR
- The message means Docker could not parse an image reference (
[registry/][namespace/]repository[:tag|@digest]) somewhere in your command. Nine times out of ten the image name is fine and the mistake is in a flag before it. - Uppercase anywhere in the repository path is the number one cause. Docker 28 names the offending part:
repository name (library/Alpine) must be lowercase. Tags may have capitals; repositories may not. - A space in an unquoted mount path (
-v $(pwd):/appwith a directory calledmy app) splits the argument and the second half becomes the "image". Quote it:-v "$(pwd):/app". - An empty variable (
docker run $IMAGE echo okwithIMAGEunset) does not produce this error any more - Docker tries to pull an image calledechoand fails withpull access denied. Give the variable a default:"${IMAGE:-myapp:1.0}". - Flags after the image name are passed to the container, not to Docker:
docker run myapp:1.0 -p 8080:80fails withexec: "-p": executable file not found in $PATH. Flags go before the image. - A trailing colon (
myapp:), two colons (myapp:v1:0), ahttps://prefix, an invisible non-breaking space from a web page, or an unset${TAG}in compose all give the bareinvalid reference format. - Every error below was reproduced on 2026-10-12 with Docker 28.0.4 on Ubuntu 24.04 and pasted as printed.
- Not your exact case? The closest post on this site is docker rename image.
In this blog post we will look at the ways to fix the docker: invalid reference format error. If you look at the error carefully then it says invalid reference format, which means the image name which you are trying to use in your Dockerfile or docker command is not acceptable.
Basically a reference in docker is a pointer to an image - registry/namespace/repository:tag. Whenever you use an image name inside your Dockerfile or a docker command, it gets parsed, and the image name has to follow certain rules. The annoying part is that Docker gives you the same error message for very different mistakes, and quite often the image name is not even the problem - a stray space or a wrong $ somewhere in the command is.
Here is how the error looks on Docker 28.0.4, for docker run, docker build and docker tag - the three places you meet it -
1$ docker run --rm Alpine:3.20 echo ok
2docker: invalid reference format: repository name (library/Alpine) must be lowercase
3
4Run 'docker run --help' for more information
5
6$ docker build -t MyApp:1.0 .
7ERROR: failed to build: invalid tag "MyApp:1.0": repository name must be lowercase
8
9$ docker tag myapp:1.0 myapp:v1:0
10Error parsing reference: "myapp:v1:0" is not a valid repository/tag: invalid reference format
(Older Docker printed docker: invalid reference format: repository name must be lowercase. followed by See 'docker run --help'.; the fixes have not changed.) Which command printed it tells you where to look -
| Command | Message prefix | Where the bad reference is |
|---|---|---|
docker run / docker create | docker: invalid reference format | the first argument that is not a flag or a flag value - often a flag has swallowed the real image name |
docker build -t | ERROR: failed to build: invalid tag "..." | the -t value |
docker tag / docker push | Error parsing reference: "..." is not a valid repository/tag | the quoted name |
docker pull | invalid reference format | the argument, typically a URL instead of a host |
docker compose up | Error response from daemon: invalid reference format | an image: line, usually with an unset ${VAR} |
Let's go through every cause I have run into, starting with the most common one -
Table of Content
- Docker image name should not contain uppercase characters
- Long docker command split over multiple lines
- ${pwd} AND $(pwd) path
- Path or volume mount with spaces
- Wrong order of arguments in docker run
- Empty or invalid tag (docker compose variable not set)
- Invalid characters in the image name (copy-paste problems)
- Rules for a valid docker image reference
- What broke when I ran this
1. Docker image name should not contain uppercase characters
The most important rule for a docker image is - the image name should always use lowercase characters and without any spaces.
Here is an example where I am trying to build an image with one uppercase character, ex - jhooq-docker-Demo
1docker build -t jhooq-docker-Demo .
Here is the error while building the docker image with one uppercase character -
1invalid argument "jhooq-docker-Demo" for "-t, --tag" flag: invalid reference format: repository name must be lowercase
2See 'docker build --help'.

Similarly if you are using the docker run command with an uppercase character in the image name then you will again end up with the same error -
1docker run -p 80:80 jhooq-docker-Demo
The above docker run command will spit out the following error -
1docker: invalid reference format: repository name must be lowercase.
2See 'docker run --help'.

This one bites a lot of people on GitHub Container Registry and Docker Hub, because the username or organisation is part of the image name - ghcr.io/RahulWagh/myapp is invalid even though the GitHub username really is RahulWagh. You have to write ghcr.io/rahulwagh/myapp.
How to fix - docker: invalid reference format: repository name must be lowercase?
The simplest way to fix the issue is to change the image name to jhooq-docker-demo so that there is no uppercase character in the image name.
Here are the correct commands -
- Docker build
1docker build -t jhooq-docker-demo .
- Docker run
1docker run -p 80:80 jhooq-docker-demo
Note that only the repository name has to be lowercase. The tag can contain uppercase letters - jhooq-docker-demo:V1.0-RC is perfectly valid.
2. Long docker command split over multiple lines
If you have a longer docker command which you need to split into multiple lines, then you should carefully use the following rules based on the shell (sh/bash, powershell, cmd) you are using -
- sh/bash : For a sh/bash-like shell, the multiline escape char is
\ - powershell : For powershell, use the backtick
` - cmd : For cmd, it is
^
This is how your docker command docker build -t jhooq-docker-demo . will look in different shells -
- sh/bash
1docker build \
2 -t jhooq-docker-demo \
3 .
- powershell
1docker build `
2 -t jhooq-docker-demo `
3 .
- cmd
1docker build ^
2 -t jhooq-docker-demo ^
3 .
The real trap here - a space after the backslash. \ (backslash, space, newline) does not continue the line, it escapes the space. The shell then starts a new command on the next line, and Docker sees -t or the image name on its own and reports invalid reference format. You cannot see the trailing space in your editor, so if you copied a multi-line command from somewhere and it fails, retype the line endings.
The same thing happens with Windows line endings (\r\n) in a .sh script - the \r ends up after the backslash. Run dos2unix script.sh or set your editor to LF.
3. ${pwd} AND $(pwd) path
If by any chance your docker command uses the current working directory for a volume mount, then you need to carefully use ${pwd} or $(pwd) based on the type of shell (powershell, sh/bash) -
- powershell - You must use
${pwd}inside your docker command
1docker run -p 8888:8888 -v ${pwd}/src:/src jhooq-docker-demo
- sh/bash - You must use
$(pwd)inside your docker command
1docker run -p 8888:8888 -v $(pwd)/src:/src jhooq-docker-demo
Why does this produce invalid reference format? In bash, ${pwd} is a variable called pwd which does not exist, so it expands to an empty string. Your command becomes docker run -p 8888:8888 -v /src:/src jhooq-docker-demo... or if the path was the whole argument, -v eats the next word, which is your image name, and Docker then tries to parse the next argument as the image. The error message points at the image, but the mistake is in the -v flag.
- cmd - On the plain Windows command prompt use
%cd%
1docker run -p 8888:8888 -v %cd%/src:/src jhooq-docker-demo
4. Path or volume mount with spaces
This is the Windows and macOS version of the previous problem. If your project lives under a path with a space, like C:\Users\Rahul Wagh\project or /Users/rahul/My Projects/app, then
1docker run -v $(pwd):/app jhooq-docker-demo
expands to docker run -v /Users/rahul/My Projects/app:/app jhooq-docker-demo. The shell splits it at the space, Projects/app:/app becomes the image name, and you get docker: invalid reference format. Reproduced in a directory called /tmp/my app -
1$ docker run --rm -v $(pwd):/app myapp:1.0
2docker: invalid reference format
3
4$ docker run --rm -v "$(pwd):/app" myapp:1.0
5ok
The command looks identical in the shell history; the only difference is the quotes.
Fix - always quote the mount -
1docker run -v "$(pwd):/app" jhooq-docker-demo
1docker run -v "${pwd}:/app" jhooq-docker-demo
The same applies to -e environment variables with spaces, e.g. -e GREETING=hello world must be -e "GREETING=hello world".
5. Wrong order of arguments in docker run
The docker run command has a strict order -
1docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Everything after the image name is passed to the container as the command. So if you put an option after the image -
1docker run jhooq-docker-demo -p 80:80
Docker runs the image with the command -p 80:80. On Docker 28 that no longer reports invalid reference format; it fails one step later, inside the container, trying to execute a program called -p -
1$ docker run --rm myapp:1.0 -p 8080:80
2docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: exec: "-p": executable file not found in $PATH
If you see exec: "-p": executable file not found (or "-e", "-v"), the argument order is the problem. A variation I see a lot in the YouTube comments -
1docker run -d --name web -p 80:80 -e nginx
Here -e consumed nginx as its value, so there is no image at all. Move all the flags before the image name -
1docker run -d --name web -p 80:80 nginx
6. Empty or invalid tag (docker compose variable not set)
A reference like myimage: (colon with nothing after it) or myimage::latest is invalid. You rarely type that by hand, but it happens all the time through variable substitution in docker compose -
1services:
2 web:
3 image: jhooq-docker-demo:${TAG}
If TAG is not set in your environment or .env file, Docker Compose renders the image as jhooq-docker-demo: and fails with
1Error response from daemon: invalid reference format
Fix - set the variable, or give it a default right in the compose file -
1services:
2 web:
3 image: jhooq-docker-demo:${TAG:-latest}
You can check what compose actually resolved with docker compose config, which prints the final file with all variables substituted. The same applies to CI pipelines where the image tag comes from a variable like $CI_COMMIT_SHA or ${{ github.sha }} that is empty in the context you are running in.
7. Invalid characters in the image name (copy-paste problems)
The last category is characters that are not allowed in a reference. The usual suspects -
- Smart quotes and long dashes - When a command is copied from a blog, a Word document or Slack, a plain
-can silently turn into–(en dash) and"into“. Docker seesjhooq–docker–demoand rejects it. Retype the dashes. - A URL instead of a name -
docker pull https://hub.docker.com/_/nginxdoes not work. The reference is justnginx(ordocker.io/library/nginx). For a private registry you give the host, not a URL:registry.jhooq.com:5000/myapp:1.0, nohttps://. - Underscore at the start or end, or double separators -
_myapp,myapp_,my__appandmy..appare all invalid. Separators (.,_,-) are only allowed between alphanumeric characters. - A path separator the wrong way - On Windows
docker build -t myapp .\or an image name containing\fails. Use/.
8. Rules for a valid docker image reference
To summarise, here is the shape of a valid reference -
1[registry-host[:port]/][namespace/]repository[:tag|@sha256:digest]
| Part | Rules | Examples |
|---|---|---|
| registry host | Optional. Hostname or IP, optional port. No http:// | docker.io, ghcr.io, 123456789012.dkr.ecr.eu-central-1.amazonaws.com, localhost:5000 |
| namespace / repository | Lowercase letters, digits, and the separators ., _, - between them. Max 255 characters in total | library/nginx, rahulwagh/jhooq-demo |
| tag | Letters (any case), digits, _, ., -. Max 128 characters. Cannot start with . or - | latest, 1.27.2, V1.0-RC |
| digest | @sha256: followed by 64 hex characters | nginx@sha256:3f2d... |
A quick way to test whether a name is valid without building anything -
1docker image inspect "your/image:name" >/dev/null
If the name is invalid you get invalid reference format immediately; if it is valid but does not exist locally you get No such image, which tells you the name itself is fine.
I hope the above approaches will help you fix your issue with the docker invalid reference format error. If you are hitting a different variant of it, drop the exact command in the comments and I will add it to the list.
9. What broke when I ran this
On 2026-10-12 I re-ran every cause in this post on Docker 28.0.4 (Ubuntu 24.04) to replace the screenshots with real text. Several behave differently from what the old version of the post claimed, so here is what actually happens now.
1. An empty variable does not give this error any more. The post used to say that docker run $IMAGE echo ok with IMAGE unset fails with invalid reference format. On Docker 28 the next word becomes the image name, and the error is about pulling it -
1$ IMAGE=""
2$ docker run --rm $IMAGE echo ok
3Unable to find image 'echo:latest' locally
4docker: Error response from daemon: pull access denied for echo, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
5
6$ docker run --rm "${IMAGE:-myapp:1.0}" echo ok
7ok
So if you see pull access denied for <the first word of your command>, suspect an empty variable before you suspect your registry login.
2. An invisible character really is invisible. I pasted a non-breaking space (U+00A0) in front of the image name. The command printed by the shell looks perfect and still fails -
1$ docker run --rm myapp:1.0 echo ok
2docker: invalid reference format
Retyping the command by hand fixed it. If a command copied from a web page, Slack or a PDF fails and you cannot see why, retype the image name.
3. A Windows path in -v gives a different error. -v 'C:\Users\rahul\app:/app' on Linux fails with invalid mode: /app, because Docker reads the C: as the host path and \Users\rahul\app as the container path, leaving /app as the (invalid) mode. On Windows itself the same syntax works, which is why it keeps appearing in copied commands.
4. The tag rules, confirmed. myapp: (trailing colon) and myapp:v1:0 (two colons) both fail; registry.example.com:5000/myapp:1.0 (a port on the host) is accepted; https://registry.example.com/myapp:1.0 is rejected with a bare invalid reference format. The host part is a hostname, never a URL.
The script that produced these outputs ran 19 commands; 10 were expected to fail and 100% of them did, with exactly the messages quoted above. Parse errors are also cheap: the successful docker build in the first section moved a 72 B Dockerfile, a 9.23 kB image manifest and the 3.63 MB Alpine base layer, spending 0.5 s on loading image metadata and 0.1 s on extracting the layer - under 1 s of real work. A reference error is never a "wait and retry" problem; it is a typo, every time.
Three related posts if the reference was fine and the next error is about what you did with it: docker rename image for the docker tag and rmi dance, driver failed programming external connectivity for the port conflict that follows a successful docker run, and how to restart a single container.
Did this save you a debugging session? Stay in the loop -
- Subscribe on YouTube - every post here has a screen-recorded companion video.
- Code on GitHub - the repositories, Terraform and scripts behind these posts.
References
- Docker forum - Docker: invalid reference format
- Docker docs - docker image tag reference rules