golang/go · error

ambiguous revision %s

Error message

ambiguous revision %s

What it means

Thrown during git revision resolution (in the Stat method) when a hash prefix supplied as the revision matches two or more distinct full commit hashes in the known refs. The prefix is ambiguous — there is no way to pick one deterministically, so resolution fails immediately rather than guessing.

Source

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

	} else if refs["refs/heads/"+rev] != "" {
		ref = "refs/heads/" + rev
		hash = refs[ref]
		rev = hash // Replace rev, because meaning of refs/heads/foo can change.
	} else if rev == "HEAD" && refs["HEAD"] != "" {
		ref = "HEAD"
		hash = refs[ref]
		rev = hash // Replace rev, because meaning of HEAD can change.
	} else if len(rev) >= minHashDigits && len(rev) <= r.hexHashLen() && AllHex(rev) {
		// At the least, we have a hash prefix we can look up after the fetch below.
		// Maybe we can map it to a full hash using the known refs.
		prefix := rev
		// Check whether rev is prefix of known ref hash.
		for k, h := range refs {
			if strings.HasPrefix(h, prefix) {
				if hash != "" && hash != h {
					// Hash is an ambiguous hash prefix.
					// More information will not change that.
					return nil, fmt.Errorf("ambiguous revision %s", rev)
				}
				if ref == "" || ref > k { // Break ties deterministically when multiple refs point at same hash.
					ref = k
				}
				rev = h
				hash = h
			}
		}
		if hash == "" && len(rev) == r.hexHashLen() { // Didn't find a ref, but rev is a full hash.
			hash = rev
		}
	} else {
		return r.unknownRevisionInfo(refs), &UnknownRevisionError{Rev: rev}
	}

	defer func() {
		if info != nil {
			info.Origin.Hash = info.Name

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Use a longer hash prefix (12+ hex chars) to disambiguate: 'go get module@abcdef123456'.
  2. Use the full 40-char commit hash to eliminate ambiguity.
  3. Reference a tag or branch name instead of a hash prefix.
  4. Use a canonical version like v1.2.3 or a full pseudo-version.

Example fix

# before: ambiguous short hash
go get example.com/mod@abc123
# after: use the full hash
go get example.com/mod@abc123def4567890abcdef1234567890abcdef12
Defensive patterns

Strategy: validation

Validate before calling

// Validate that a hash prefix is long enough to be unambiguous
// before calling Stat
func minHashPrefixLen() int { return 12 }

func validateHashPrefix(rev string) error {
    if !codehost.AllHex(rev) { return nil }
    if len(rev) >= 4 && len(rev) < minHashPrefixLen() {
        return fmt.Errorf("hash prefix %q too short; use at least %d hex chars to avoid ambiguity", rev, minHashPrefixLen())
    }
    return nil
}

Type guard

null

Try / catch

// On 'ambiguous revision', retry with the full hash
info, err := repo.Stat(ctx, shortHash)
if err != nil && strings.Contains(err.Error(), "ambiguous revision") {
    // resolve the full hash externally and retry
    full, rerr := resolveFullHash(shortHash)
    if rerr != nil { return rerr }
    return repo.Stat(ctx, full)
}

Prevention

When it happens

Trigger: Calling Stat (via go get module@<short-hash>) where the short hash prefix matches multiple commits across different refs/tags. The loop over refs finds two different full hashes both starting with the prefix.

Common situations: Using a very short hash prefix (e.g. 4-7 chars) in a repo with many commits; a repo where two commits happen to share a long prefix; pseudo-version construction with an insufficiently specific hash.

Related errors


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