golang/go · error

ref deleted

Error message

ref %q deleted

What it means

Thrown by gitRepo.CheckReuse when the previously recorded ref (old.Ref) no longer exists in the remote's ref set (loaded via ls-remote). This means the branch or tag that the cached checkout was based on has been deleted upstream, so the cached data may no longer be reachable.

Solutions

  1. Update the module to a version that exists: 'go get module@<tag-or-hash>'.
  2. If the ref was renamed, update your dependency to the new ref.
  3. Pin to a specific commit hash or a semantic version tag instead of a mutable branch.
  4. Contact the module maintainer if the ref was deleted unintentionally.

Example fix

// before: pinned to a deleted branch
go get example.com/mod@some-branch
// after: pin to a tag or hash
go get example.com/mod@v1.2.3
// or
go get example.com/mod@abc123def456
Defensive patterns

Strategy: fallback

Validate before calling

null

Type guard

null

Try / catch

// On 'ref deleted', fall back to a fresh Stat which may find the commit by hash
err := repo.CheckReuse(ctx, old, subdir)
if err != nil && strings.Contains(err.Error(), "deleted") {
    info, ferr := repo.Stat(ctx, old.Hash)
    if ferr == nil { return useInfo(info) }
    return ferr
}

Prevention

When it happens

Trigger: CheckReuse after the upstream deleted the branch/tag that old.Ref pointed to (e.g. a feature branch merged and removed, or a tag was deleted). The local refs map from ls-remote no longer contains old.Ref.

Common situations: A module pinned to a branch that was deleted upstream; a tag removed and recreated; force-push history rewrite that dropped the ref; GitHub auto-deleting branches after merge.

Related errors


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

Appendix: source

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

	// Note: Can have Hash with no Ref and no TagSum and no RepoSum,
	// meaning the Hash simply has to remain in the repo.
	// 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")
		}

View on GitHub (pinned to b6b368adc5)