{"record":{"id":"8279d5e6aac1a116","repo":"golang/go","slug":"origin-moved-from-v-q-q-to-v-q-q","errorCode":null,"errorMessage":"origin moved from %v %q %q to %v %q %q","messagePattern":"origin moved from (.+?) %q %q to (.+?) %q %q","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/modfetch/codehost/vcs.go","lineNumber":388,"sourceCode":"\torigin := &Origin{\n\t\tVCS:     r.cmd.vcs,\n\t\tURL:     r.remote,\n\t\tRepoSum: r.repoSum,\n\t}\n\tr.repoSumOnce.Do(func() { r.loadRepoSum(ctx) })\n\torigin.RepoSum = r.repoSum\n\treturn origin\n}\n\nfunc (r *vcsRepo) CheckReuse(ctx context.Context, old *Origin, subdir string) error {\n\tif old == nil {\n\t\treturn fmt.Errorf(\"missing origin\")\n\t}\n\tif old.VCS != r.cmd.vcs || old.URL != r.remote {\n\t\treturn fmt.Errorf(\"origin moved from %v %q to %v %q\", old.VCS, old.URL, r.cmd.vcs, r.remote)\n\t}\n\tif old.Subdir != subdir {\n\t\treturn fmt.Errorf(\"origin moved from %v %q %q to %v %q %q\", old.VCS, old.URL, old.Subdir, r.cmd.vcs, r.remote, subdir)\n\t}\n\n\tif old.Ref == \"\" && old.RepoSum == \"\" && old.Hash != \"\" {\n\t\t// Hash has to remain in repo.\n\t\thash, err := r.lookupRef(ctx, old.Hash)\n\t\tif err == nil && hash == old.Hash {\n\t\t\treturn nil\n\t\t}\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"looking up hash: %v\", err)\n\t\t}\n\t\treturn fmt.Errorf(\"hash changed\") // weird but maybe they made a tag\n\t}\n\n\tif old.Ref != \"\" && old.RepoSum == \"\" {\n\t\thash, err := r.lookupRef(ctx, old.Ref)\n\t\tif err == nil && hash != \"\" && hash == old.Hash {\n\t\t\treturn nil","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modfetch/codehost/vcs.go#L370-L406","documentation":"CheckReuse's second move-detection: the VCS and URL match but the subdir component differs. The %v/%q tuple shows old (VCS, URL, Subdir) vs new (VCS, URL, subdir argument). Means the module is being resolved from a different subdirectory of the same repo than before.","triggerScenarios":"Same repo URL but the caller passed a different subdir to CheckReuse than what is recorded in old.Subdir. Happens when a go-import meta tag's subdir attribute changed (new in Go 1.25) or the codeRoot computation shifted.","commonSituations":"A monorepo moved the module into a different subdirectory and updated its meta tag; the cached origin's Subdir is stale after a repo reorganisation; a hand-edited go.mod with a mismatched path.","solutions":["Clear the module cache entry: `go clean -modcache` or delete GOMODCACHE/cache/download/<module>/ and re-download.","Verify the go-import meta tag's subdir is stable and matches the module's actual location in the repo.","Confirm the import path in go.mod matches the path the meta tag advertises."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"func subdirMatches(old *codehost.Origin, subdir string) bool {\n    return old != nil && old.Subdir == subdir\n}","typeGuard":null,"tryCatchPattern":"if err := repo.CheckReuse(ctx, old, subdir); err != nil {\n    if strings.Contains(err.Error(), \"origin moved\") && strings.Contains(err.Error(), old.Subdir) {\n        // subdir changed — invalidate and re-resolve\n    }\n}","preventionTips":["Keep go-import subdir attributes stable; document moves in release notes.","Flush the module cache after restructuring a monorepo's module layout."],"tags":["vcs","checkreuse","subdir","monorepo","origin"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}