{"record":{"id":"360b800daf6db277","repo":"golang/go","slug":"tags-changed","errorCode":null,"errorMessage":"tags changed","messagePattern":"tags changed","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src/cmd/go/internal/modfetch/codehost/git.go","lineNumber":236,"sourceCode":"\t\treturn r.refsErr\n\t}\n\n\tif old.Ref != \"\" {\n\t\thash, ok := r.refs[old.Ref]\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"ref %q deleted\", old.Ref)\n\t\t}\n\t\tif hash != old.Hash {\n\t\t\treturn fmt.Errorf(\"ref %q moved from %s to %s\", old.Ref, old.Hash, hash)\n\t\t}\n\t}\n\tif old.TagSum != \"\" {\n\t\ttags, err := r.Tags(ctx, old.TagPrefix)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif tags.Origin.TagSum != old.TagSum {\n\t\t\treturn fmt.Errorf(\"tags changed\")\n\t\t}\n\t}\n\tif old.RepoSum != \"\" {\n\t\tif r.repoSum(r.refs) != old.RepoSum {\n\t\t\treturn fmt.Errorf(\"refs changed\")\n\t\t}\n\t}\n\treturn nil\n}\n\n// loadRefs loads heads and tags references from the remote into the map r.refs.\n// The result is cached in memory.\nfunc (r *gitRepo) loadRefs(ctx context.Context) (map[string]string, error) {\n\tif r.local { // Return results from the cache if local only.\n\t\t// In the future, we could consider loading r.refs using local git commands\n\t\t// if desired.\n\t\treturn nil, nil\n\t}","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modfetch/codehost/git.go#L218-L254","documentation":"Thrown by gitRepo.CheckReuse when old.TagSum is set and the current tag set checksum (computed over tags matching old.TagPrefix) differs from the recorded value. This means tags were added, removed, or changed in the relevant prefix since the cache entry was written.","triggerScenarios":"CheckReuse where the upstream repo's tags (under the recorded prefix) have changed — new version tags published, old tags removed. The TagSum is a checksum over the tag set, so any change triggers this.","commonSituations":"A new version of the module was tagged upstream since your last fetch; tags were reorganized; depending on a module via 'latest' or a pseudo-version that depends on tag availability. This is expected behavior when a module releases a new version.","solutions":["This is usually benign — just re-fetch: 'go mod download' or 'go get module@latest'.","If you want stability, pin to a specific version: 'go get module@v1.2.3'.","Run 'go mod tidy' to update go.sum entries.","If using GOPROXY=off, switch to a proxy or direct to allow re-fetch."],"exampleFix":"# before: cache has stale tag set\ngo build ./...  # fails with 'tags changed'\n# after: re-fetch\nGONOSUMCHECK=1 go mod download\ngo build ./...","handlingStrategy":"fallback","validationCode":"null","typeGuard":"null","tryCatchPattern":"// 'tags changed' is expected when upstream releases new versions; re-fetch\nerr := repo.CheckReuse(ctx, old, subdir)\nif err != nil && strings.Contains(err.Error(), \"tags changed\") {\n    // force re-fetch\n    info, ferr := repo.Stat(ctx, rev)\n    if ferr == nil { return useInfo(info) }\n    return ferr\n}","preventionTips":["Treat 'tags changed' / 'refs changed' as soft cache invalidation, not hard errors.","Pin to exact versions to make these checks deterministic.","Keep the cache fresh with periodic 'go mod download'."],"tags":["git","cache-reuse","tags","upstream-change","benign"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}