python-poetry/poetry · error · PoetryRuntimeError

<error>Failed to clone {url} at '{refspec.key}', verify ref

Error message

<error>Failed to clone {url} at '{refspec.key}', verify ref exists on remote.</>

What it means

In the dulwich-based _clone, after fetching remote refs, refspec.resolve(remote_refs, repo=local) is called. A KeyError from resolve means the requested branch/tag/revision is not present among the advertised remote refs, so PoetryRuntimeError is raised telling you to verify the ref exists on the remote.

Source

Thrown at src/poetry/vcs/git/backend.py:345

        ref spec.
        """
        local: Repo
        if not target.exists():
            local = Repo.init(str(target), mkdir=True)
            porcelain.remote_add(local, "origin", url)
        else:
            local = Repo(str(target))

        remote_refs = cls._fetch_remote_refs(url=url, local=local)

        logger.debug(
            "Cloning <c2>%s</> at '<c2>%s</>' to <c1>%s</>", url, refspec.key, target
        )

        try:
            refspec.resolve(remote_refs=remote_refs, repo=local)
        except KeyError:  # branch / ref does not exist
            raise PoetryRuntimeError.create(
                reason=f"<error>Failed to clone {url} at '{refspec.key}', verify ref exists on remote.</>",
                info=[
                    ERROR_MESSAGE_NOTE,
                    ERROR_MESSAGE_PROBLEMS_SECTION_START_NETWORK_ISSUES,
                    ERROR_MESSAGE_BAD_REVISION.format(revision=refspec.key),
                ],
            )

        try:
            # ensure local HEAD matches remote
            ref = remote_refs.refs[Ref(b"HEAD")]
            if ref is not None:
                local.refs[Ref(b"HEAD")] = ref
        except ValueError:
            raise PoetryRuntimeError.create(
                reason=f"<error>Failed to clone {url} at '{refspec.key}', verify ref exists on remote.</>",
                info=[
                    ERROR_MESSAGE_NOTE,

View on GitHub (pinned to 92b74dcfe3)

Solutions

  1. Run `git ls-remote <url>` to confirm the ref is actually advertised.
  2. Fix the rev/branch/tag in pyproject.toml to an existing remote ref.
  3. Push the missing ref to the remote if it should be there.
  4. Use an explicit full commit sha to avoid ambiguity.

Example fix

# before
lib = { git = "https://github.com/acme/lib.git", tag = "v1.2" }  # tag does not exist
# after - verify with: git ls-remote --tags https://github.com/acme/lib.git
lib = { git = "https://github.com/acme/lib.git", tag = "v1.2.3" }
Defensive patterns

Strategy: validation

Validate before calling

import subprocess

def remote_has_ref(url: str, ref: str) -> bool:
    out = subprocess.run(
        ['git', 'ls-remote', url], capture_output=True, text=True,
    ).stdout
    return any(ref in line for line in out.splitlines())

Try / catch

from poetry.exceptions import PoetryRuntimeError
try:
    ...  # operation triggering a dulwich clone
except PoetryRuntimeError as e:
    if 'verify ref exists on remote' in str(e):
        raise

Prevention

When it happens

Trigger: A git dependency whose rev/branch/tag is not advertised by the remote (typo, deleted ref, ref only in a fork), cloned via dulwich.

Common situations: Branch renamed or deleted upstream; rev is a short sha ambiguous or absent; pointing at a tag that doesn't exist; ref lives only on a different remote/fork.

Related errors


AI-assisted analysis of python-poetry/poetry@92b74dcfe3 (2026-08-04). Data as JSON: /data/errors/fa8a0ab03ce436a3.json. Report an issue: GitHub.