{"record":{"id":"32b18d03c25f155e","repo":"golang/go","slug":"ambiguous-revision-s","errorCode":null,"errorMessage":"ambiguous revision %s","messagePattern":"ambiguous revision (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/modfetch/codehost/git.go","lineNumber":490,"sourceCode":"\t} else if refs[\"refs/heads/\"+rev] != \"\" {\n\t\tref = \"refs/heads/\" + rev\n\t\thash = refs[ref]\n\t\trev = hash // Replace rev, because meaning of refs/heads/foo can change.\n\t} else if rev == \"HEAD\" && refs[\"HEAD\"] != \"\" {\n\t\tref = \"HEAD\"\n\t\thash = refs[ref]\n\t\trev = hash // Replace rev, because meaning of HEAD can change.\n\t} else if len(rev) >= minHashDigits && len(rev) <= r.hexHashLen() && AllHex(rev) {\n\t\t// At the least, we have a hash prefix we can look up after the fetch below.\n\t\t// Maybe we can map it to a full hash using the known refs.\n\t\tprefix := rev\n\t\t// Check whether rev is prefix of known ref hash.\n\t\tfor k, h := range refs {\n\t\t\tif strings.HasPrefix(h, prefix) {\n\t\t\t\tif hash != \"\" && hash != h {\n\t\t\t\t\t// Hash is an ambiguous hash prefix.\n\t\t\t\t\t// More information will not change that.\n\t\t\t\t\treturn nil, fmt.Errorf(\"ambiguous revision %s\", rev)\n\t\t\t\t}\n\t\t\t\tif ref == \"\" || ref > k { // Break ties deterministically when multiple refs point at same hash.\n\t\t\t\t\tref = k\n\t\t\t\t}\n\t\t\t\trev = h\n\t\t\t\thash = h\n\t\t\t}\n\t\t}\n\t\tif hash == \"\" && len(rev) == r.hexHashLen() { // Didn't find a ref, but rev is a full hash.\n\t\t\thash = rev\n\t\t}\n\t} else {\n\t\treturn r.unknownRevisionInfo(refs), &UnknownRevisionError{Rev: rev}\n\t}\n\n\tdefer func() {\n\t\tif info != nil {\n\t\t\tinfo.Origin.Hash = info.Name","sourceCodeStart":472,"sourceCodeEnd":508,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modfetch/codehost/git.go#L472-L508","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use a longer hash prefix (12+ hex chars) to disambiguate: 'go get module@abcdef123456'.","Use the full 40-char commit hash to eliminate ambiguity.","Reference a tag or branch name instead of a hash prefix.","Use a canonical version like v1.2.3 or a full pseudo-version."],"exampleFix":"# before: ambiguous short hash\ngo get example.com/mod@abc123\n# after: use the full hash\ngo get example.com/mod@abc123def4567890abcdef1234567890abcdef12","handlingStrategy":"validation","validationCode":"// Validate that a hash prefix is long enough to be unambiguous\n// before calling Stat\nfunc minHashPrefixLen() int { return 12 }\n\nfunc validateHashPrefix(rev string) error {\n    if !codehost.AllHex(rev) { return nil }\n    if len(rev) >= 4 && len(rev) < minHashPrefixLen() {\n        return fmt.Errorf(\"hash prefix %q too short; use at least %d hex chars to avoid ambiguity\", rev, minHashPrefixLen())\n    }\n    return nil\n}","typeGuard":"null","tryCatchPattern":"// On 'ambiguous revision', retry with the full hash\ninfo, err := repo.Stat(ctx, shortHash)\nif err != nil && strings.Contains(err.Error(), \"ambiguous revision\") {\n    // resolve the full hash externally and retry\n    full, rerr := resolveFullHash(shortHash)\n    if rerr != nil { return rerr }\n    return repo.Stat(ctx, full)\n}","preventionTips":["Use 12+ hex character prefixes (the canonical ShortenSHA1 length) for commit references.","Prefer full 40-char hashes or version tags over short prefixes.","Document the minimum prefix length for your team's go get usage."],"tags":["git","revision-resolution","hash-prefix","ambiguous"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}