golang/go · warning
hash changed
Error message
hash changed
What it means
Hash verification branch: lookupRef succeeded but returned a different hash than old.Hash. The inline comment says 'weird but maybe they made a tag' — this means the ref now resolves to a different commit, indicating the tag/branch was reassigned or the repo was rewritten.
Source
Thrown at src/cmd/go/internal/modfetch/codehost/vcs.go:400
return fmt.Errorf("missing origin")
}
if old.VCS != r.cmd.vcs || old.URL != r.remote {
return fmt.Errorf("origin moved from %v %q to %v %q", old.VCS, old.URL, r.cmd.vcs, r.remote)
}
if old.Subdir != subdir {
return fmt.Errorf("origin moved from %v %q %q to %v %q %q", old.VCS, old.URL, old.Subdir, r.cmd.vcs, r.remote, subdir)
}
if old.Ref == "" && old.RepoSum == "" && old.Hash != "" {
// Hash has to remain in repo.
hash, err := r.lookupRef(ctx, old.Hash)
if err == nil && hash == old.Hash {
return nil
}
if err != nil {
return fmt.Errorf("looking up hash: %v", err)
}
return fmt.Errorf("hash changed") // weird but maybe they made a tag
}
if old.Ref != "" && old.RepoSum == "" {
hash, err := r.lookupRef(ctx, old.Ref)
if err == nil && hash != "" && hash == old.Hash {
return nil
}
}
r.repoSumOnce.Do(func() { r.loadRepoSum(ctx) })
if r.repoSum != "" {
if old.RepoSum == "" {
return fmt.Errorf("non-specific origin")
}
if old.RepoSum != r.repoSum {
return fmt.Errorf("repo changed")
}
return nilView on GitHub (pinned to b6b368adc5)
Solutions
- Pin to an explicit semver tag in go.mod instead of a branch or commit that can move.
- Run `go clean -modcache` and re-resolve — the new hash becomes the baseline.
- If you control the upstream, avoid retagging; if a yank is needed, use module retraction instead.
- Audit go.sum for the affected module and update checksums after confirming the new commit is legitimate.
Defensive patterns
Strategy: validation
Validate before calling
func hashStable(oldHash, resolvedHash string) bool {
return oldHash == resolvedHash
} Prevention
- Never retag released versions — use module retraction instead.
- Avoid force-pushing shared release branches.
- Pin go.mod entries to canonical semver tags.
When it happens
Trigger: old.Hash recorded a specific commit, lookupRef(old.Hash) returns a non-matching hash — upstream force-pushed, retagged, or rewrote history at that name.
Common situations: Upstream retagged a release to a different commit (rare but happens after yanks); a branch used as a ref was reset; repository was rewritten with git filter-branch.
Related errors
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/50a75531d03f6236.
Report an issue: GitHub.