{"record":{"id":"323af472930af75a","repo":"golang/go","slug":"proxy-returned-info-for-version-s-instead-of-requ","errorCode":null,"errorMessage":"proxy returned info for version %s instead of requested version","messagePattern":"proxy returned info for version (.+?) instead of requested version","errorType":"exception","errorClass":"module.VersionError","httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/modfetch/proxy.go","lineNumber":386,"sourceCode":"\nfunc (p *proxyRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {\n\tencRev, err := module.EscapeVersion(rev)\n\tif err != nil {\n\t\treturn nil, p.versionError(rev, err)\n\t}\n\tdata, err := p.getBytes(ctx, \"@v/\"+encRev+\".info\")\n\tif err != nil {\n\t\treturn nil, p.versionError(rev, err)\n\t}\n\tinfo := new(RevInfo)\n\tif err := json.Unmarshal(data, info); err != nil {\n\t\treturn nil, p.versionError(rev, fmt.Errorf(\"invalid response from proxy %q: %w\", p.redactedBase, err))\n\t}\n\tif info.Version != rev && rev == module.CanonicalVersion(rev) && module.Check(p.path, rev) == nil {\n\t\t// If we request a correct, appropriate version for the module path, the\n\t\t// proxy must return either exactly that version or an error — not some\n\t\t// arbitrary other version.\n\t\treturn nil, p.versionError(rev, fmt.Errorf(\"proxy returned info for version %s instead of requested version\", info.Version))\n\t}\n\treturn info, nil\n}\n\nfunc (p *proxyRepo) Latest(ctx context.Context) (*RevInfo, error) {\n\tdata, err := p.getBytes(ctx, \"@latest\")\n\tif err != nil {\n\t\tif !errors.Is(err, fs.ErrNotExist) {\n\t\t\treturn nil, p.versionError(\"\", err)\n\t\t}\n\t\treturn p.latest(ctx)\n\t}\n\tinfo := new(RevInfo)\n\tif err := json.Unmarshal(data, info); err != nil {\n\t\treturn nil, p.versionError(\"\", fmt.Errorf(\"invalid response from proxy %q: %w\", p.redactedBase, err))\n\t}\n\treturn info, nil\n}","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modfetch/proxy.go#L368-L404","documentation":"proxyRepo.Stat verifies the .info response: if the requested version was already canonical and module.Check accepted it for the path, the proxy MUST echo that exact version. Returning a different version (e.g. mapping v1.2.3 to v1.2.4) is a protocol violation and is rejected.","triggerScenarios":"info.Version != rev AND rev == module.CanonicalVersion(rev) AND module.Check(path, rev) == nil. The proxy substituted a different version in its response.","commonSituations":"A proxy that 'resolves' versions upward (e.g. redirects v1.2.3 to latest v1.2.x); a redirecting mirror that rewrites versions; a fork proxy mapping tags inconsistently.","solutions":["Switch to a standards-compliant proxy (https://proxy.golang.org,direct).","Pin the exact version you want and report the bug to the proxy operator.","If self-hosting, ensure Stat returns Version == requested canonical version (or a 404/410)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before trusting Stat output, ensure the proxy echoes the requested version.\n// (mirrors the go command's own invariant)\nfunc statEchoes(repo Repo, ctx context.Context, rev string) error {\n    info, err := repo.Stat(ctx, rev)\n    if err != nil { return err }\n    if info.Version != rev { return fmt.Errorf(\"proxy echoed %s, want %s\", info.Version, rev) }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if _, err := repo.Stat(ctx, rev); err != nil {\n    if strings.Contains(err.Error(), \"instead of requested version\") {\n        // switch GOPROXY entry or fall back to direct\n    }\n}","preventionTips":["Pin module versions explicitly.","Avoid proxies that auto-upgrade patch versions."],"tags":["goproxy","versioning","proxy","stat"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}