golang/go · error

revision does not exist locally: %s

Error message

revision does not exist locally: %s

What it means

Thrown by gitRepo.Stat when operating in local-only mode (r.local == true) and the requested revision cannot be found via local git operations after all local lookup paths are exhausted. In local mode, the tool will not perform network fetches, so a missing revision is a hard failure.

Source

Thrown at src/cmd/go/internal/modfetch/codehost/git.go:545

	if !didStatLocal {
		if info, err := r.statLocal(ctx, rev, hash); err == nil {
			tag, fromTag := strings.CutPrefix(ref, "refs/tags/")
			if fromTag && !slices.Contains(info.Tags, tag) {
				// The local repo includes the commit hash we want, but it is missing
				// the corresponding tag. Add that tag and try again.
				_, err := r.runGit(ctx, "git", "tag", "--end-of-options", tag, hash)
				if err != nil {
					return nil, err
				}
				r.localTags.Store(tag, true)
				return r.statLocal(ctx, rev, ref)
			}
			return info, err
		}
	}

	if r.local { // at this point, we have determined that we need to fetch rev, fail early if local only mode.
		return nil, fmt.Errorf("revision does not exist locally: %s", rev)
	}

	// If we know a specific commit we need and its ref, fetch it.
	// We do NOT fetch arbitrary hashes (when we don't know the ref)
	// because we want to avoid ever importing a commit that isn't
	// reachable from refs/tags/* or refs/heads/* or HEAD.
	// Both Gerrit and GitHub expose every CL/PR as a named ref,
	// and we don't want those commits masquerading as being real
	// pseudo-versions in the main repo.
	if r.fetchLevel <= fetchSome && ref != "" && hash != "" {
		r.fetchLevel = fetchSome
		var refspec string
		if ref == "HEAD" {
			// Fetch the hash but give it a local name (refs/dummy),
			// because that triggers the fetch behavior of creating any
			// other known remote tags for the hash. We never use
			// refs/dummy (it's not refs/tags/dummy) and it will be
			// overwritten in the next command, and that's fine.

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Verify the revision exists locally: 'cd <local_path> && git rev-parse <rev>'.
  2. Fetch/update the local repo: 'cd <local_path> && git fetch --all && git checkout <rev>'.
  3. Check for typos in the version string in go.mod.
  4. If a shallow clone, deepen it: 'git fetch --unshallow'.

Example fix

# before: local replace missing the tag
replace example.com/mod => ./local-mod
# go.mod requires v1.5.0 but ./local-mod doesn't have it
cd ./local-mod && git fetch --tags
go mod tidy
# after
go build ./...
Defensive patterns

Strategy: validation

Validate before calling

// Before relying on a local replace, verify the revision exists
func validateLocalRev(repoDir, rev string) error {
    cmd := exec.Command("git", "-C", repoDir, "rev-parse", "--verify", rev)
    if out, err := cmd.CombinedOutput(); err != nil {
        return fmt.Errorf("revision %q not found in %s: %s", rev, repoDir, out)
    }
    return nil
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Stat(ctx, rev) on a gitRepo opened with local=true (e.g. a replace directive pointing at a local path) where rev is a tag, branch, or hash that does not exist in that local repo. The method tried statLocal and local tags already.

Common situations: A local replace directive pointing at a checkout that doesn't have the requested tag/branch; the local repo is shallow and missing the commit; the revision string is misspelled; the local checkout is behind upstream.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/deb95cc5a58f2b0d. Report an issue: GitHub.