Skip to content

/errors/git/couldnt-find-remote-ref

fatal: couldn't find remote ref

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · git version 2.55.0.windows.5updated
tool
Git
exit code
128
versions
Git 2.x
os
any

fatal: couldn't find remote ref NAME means the remote repository has no branch or tag called NAME. Git contacted the remote successfully; the name you asked for is not in its list of refs. The usual causes are a typo, master versus main, or a branch that was deleted after a merge.

Reproduce it

bash
git init -q --bare remote.git
git init -q work
cd work
git fetch ../remote.git nope

Output · exit 128

fatal: couldn't find remote ref nope

See what the remote has

bash
git init -q --bare remote.git
git init -q work
cd work
git -c user.name=t -c user.email=t@example.com commit -q --allow-empty -m init
git push -q ../remote.git HEAD:refs/heads/main
git ls-remote --heads ../remote.git | sed 's/^[0-9a-f]*/HASH/'
git fetch ../remote.git main

Output

HASH	refs/heads/main
From ../remote
 * branch            main       -> FETCH_HEAD

git ls-remote --heads prints the commit hash and the full ref name of every branch on the remote. Pass the name without the refs/heads/ prefix to git fetch, git pull and git clone --branch.

The same mistake in pull, clone and tags

The message changes slightly with the command, and so does the exit status:

bash
git init -q --bare remote.git
git init -q -b main work
cd work
git commit -q --allow-empty -m init
git push -q ../remote.git HEAD:refs/heads/main
git remote add origin ../remote.git
git pull origin Main
echo "exit status: $?"
git fetch origin tag v9
echo "exit status: $?"
cd ..
git clone -q --branch nope remote.git copy
echo "exit status: $?"

Output

fatal: couldn't find remote ref Main
exit status: 1
fatal: couldn't find remote ref refs/tags/v9
exit status: 128
fatal: Remote branch nope not found in upstream origin
exit status: 128
  • Main is not main: git matches the name against the remote's list of refs exactly, so the case must match.
  • For a tag, the message shows the full ref (refs/tags/v9), which tells you git looked among tags, not branches.
  • git clone --branch uses its own wording, Remote branch NAME not found in upstream origin.

How to recognise the cause

ClueLikely cause
ls-remote shows the name with different case or spellingTypo or wrong case in the command
ls-remote shows main but the command says master (or the reverse)Default branch name mismatch, common in old scripts and tutorials
The branch appears in git branch -r but not in ls-remoteDeleted on the server; your remote-tracking copy is stale
The branch is in git branch but not in git branch -rIt was never pushed
ls-remote on another remote shows itThe command used the wrong remote, such as origin instead of upstream

Check before fetching

In scripts, test whether the remote has the branch before fetching it. git ls-remote --exit-code --heads origin NAME exits with status 2 when nothing matches and 0 when the branch exists, without downloading any objects. git remote show origin also prints the remote's HEAD branch, which answers the main versus master question in one line.

Prevention

Avoid hard-coding master or main in scripts and CI jobs; read the default branch from the remote, or pass the branch name as a parameter. Run git fetch --prune (or set fetch.prune=true) so branches deleted after a merge disappear from your clone instead of looking available.

FAQ

Why does git branch -r still show the branch?

git branch -r lists remote-tracking refs stored in your clone, which are only updated when you fetch. If the branch was deleted on the server, git fetch --prune removes the stale copy.

Why does git clone --branch print a different message?

git clone reports a missing branch as Remote branch NAME not found in upstream origin. The cause is the same, the name is not in the remote's list of refs.

Does git pull exit with 128 too?

No. git fetch and git clone exit with 128, while git pull prints the same fatal message and exits with 1, as the example on this page shows. Scripts should test for a non-zero status rather than a specific code.

Sources