golang/go · error

origin moved from %v %q to %v %q

Error message

origin moved from %v %q to %v %q

What it means

CheckReuse compares the old origin's VCS type and URL against the current repo. If either differs, the origin is considered to have moved and reuse is refused. The %v/%q pair shows old vs new VCS and URL.

Source

Thrown at src/cmd/go/internal/modfetch/codehost/vcs.go:385

// repoSumOrigin returns an Origin containing a RepoSum.
func (r *vcsRepo) repoSumOrigin(ctx context.Context) *Origin {
	origin := &Origin{
		VCS:     r.cmd.vcs,
		URL:     r.remote,
		RepoSum: r.repoSum,
	}
	r.repoSumOnce.Do(func() { r.loadRepoSum(ctx) })
	origin.RepoSum = r.repoSum
	return origin
}

func (r *vcsRepo) CheckReuse(ctx context.Context, old *Origin, subdir string) error {
	if old == nil {
		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 == "" {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Run `go clean -modcache` (or remove the specific module directory) so the stale origin is discarded and re-fetched from the new remote.
  2. Align the replace directive with the new upstream URL.
  3. Update the vanity server's go-import meta tag consistently so all clients see the same VCS+URL.

Example fix

// before — cache says hg https://old.example.org/m, meta tag now points to https://new.example.org/m
$ go build
// error: origin moved from hg "https://old.example.org/m" to hg "https://new.example.org/m"

// after
$ go clean -modcache && go build
Defensive patterns

Strategy: fallback

Validate before calling

func originMatches(old *codehost.Origin, vcs, url string) bool {
    return old != nil && old.VCS == vcs && old.URL == url
}

Try / catch

if err := repo.CheckReuse(ctx, old, subdir); err != nil {
    if strings.HasPrefix(err.Error(), "origin moved") {
        // upstream moved — invalidate cache and re-download
        go cleanModCache(modulePath)
    }
}

Prevention

When it happens

Trigger: A cached Origin records VCS=hg URL=A, but the current repo is VCS=hg URL=B (or the VCS type itself changed). Typical when a vanity server redirected the import path to a different backing repo.

Common situations: Upstream project migrated hosts (e.g. Bitbucket to GitHub) and updated the go-import meta tag; a vanity server rotated its canonical URL; a replace directive points to a different remote than the cached origin.

Related errors


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