golang/go · warning
ref %q moved from %s to %s
Error message
ref %q moved from %s to %s
What it means
Thrown by gitRepo.CheckReuse when the recorded ref still exists in the remote refs but now points to a different hash than old.Hash — the ref was updated (e.g. branch moved forward, tag was moved). This means the cached checkout may be stale relative to the ref it claims to track.
Source
Thrown at src/cmd/go/internal/modfetch/codehost/git.go:227
// In that case we assume it does in the absence of any real way to check.
// But if neither Hash nor TagSum is present, we have nothing to check,
// which we take to mean we didn't record enough information to be sure.
if old.Hash == "" && old.TagSum == "" && old.RepoSum == "" {
return fmt.Errorf("non-specific origin")
}
r.loadRefs(ctx)
if r.refsErr != nil {
return r.refsErr
}
if old.Ref != "" {
hash, ok := r.refs[old.Ref]
if !ok {
return fmt.Errorf("ref %q deleted", old.Ref)
}
if hash != old.Hash {
return fmt.Errorf("ref %q moved from %s to %s", old.Ref, old.Hash, hash)
}
}
if old.TagSum != "" {
tags, err := r.Tags(ctx, old.TagPrefix)
if err != nil {
return err
}
if tags.Origin.TagSum != old.TagSum {
return fmt.Errorf("tags changed")
}
}
if old.RepoSum != "" {
if r.repoSum(r.refs) != old.RepoSum {
return fmt.Errorf("refs changed")
}
}
return nil
}View on GitHub (pinned to b6b368adc5)
Solutions
- Update the dependency to the new ref: 'go get module@<ref>'.
- Pin to a specific immutable version tag or commit hash instead of a mutable branch.
- If a moved tag is the issue, coordinate with the upstream maintainer.
- Run 'go mod tidy' after updating to reconcile transitive deps.
Example fix
// before: tracking a branch that moved go get example.com/mod@main // after: pin to a specific tag go get example.com/mod@v1.4.0
Defensive patterns
Strategy: fallback
Validate before calling
null
Type guard
null
Try / catch
// On 'ref moved', re-stat against the new ref
err := repo.CheckReuse(ctx, old, subdir)
if err != nil && strings.Contains(err.Error(), "moved") {
// accept that the ref advanced; re-resolve
info, ferr := repo.Stat(ctx, old.Ref)
if ferr == nil { return useInfo(info) }
return ferr
} Prevention
- Avoid depending on mutable branch refs for reproducible builds.
- Pin to semantic version tags or commit hashes in go.mod.
- Run 'go mod tidy' regularly to catch ref drift early.
When it happens
Trigger: CheckReuse on a module sourced from a mutable ref (branch or moved tag) where the upstream ref now resolves to a different commit. The cached repo was recorded against old.Hash but the remote now has a new hash for old.Ref.
Common situations: Depending on a branch (not a tag) that received new commits; a tag that was force-moved (unusual but possible);a pseudo-version whose underlying ref advanced; using 'latest' or a branch name in go get.
Related errors
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/334bcfd4d5baa6cf.
Report an issue: GitHub.