golang/go · error · module.VersionError
proxy returned info for version %s instead of requested vers
Error message
proxy returned info for version %s instead of requested version
What it means
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.
Source
Thrown at src/cmd/go/internal/modfetch/proxy.go:386
func (p *proxyRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
encRev, err := module.EscapeVersion(rev)
if err != nil {
return nil, p.versionError(rev, err)
}
data, err := p.getBytes(ctx, "@v/"+encRev+".info")
if err != nil {
return nil, p.versionError(rev, err)
}
info := new(RevInfo)
if err := json.Unmarshal(data, info); err != nil {
return nil, p.versionError(rev, fmt.Errorf("invalid response from proxy %q: %w", p.redactedBase, err))
}
if info.Version != rev && rev == module.CanonicalVersion(rev) && module.Check(p.path, rev) == nil {
// If we request a correct, appropriate version for the module path, the
// proxy must return either exactly that version or an error — not some
// arbitrary other version.
return nil, p.versionError(rev, fmt.Errorf("proxy returned info for version %s instead of requested version", info.Version))
}
return info, nil
}
func (p *proxyRepo) Latest(ctx context.Context) (*RevInfo, error) {
data, err := p.getBytes(ctx, "@latest")
if err != nil {
if !errors.Is(err, fs.ErrNotExist) {
return nil, p.versionError("", err)
}
return p.latest(ctx)
}
info := new(RevInfo)
if err := json.Unmarshal(data, info); err != nil {
return nil, p.versionError("", fmt.Errorf("invalid response from proxy %q: %w", p.redactedBase, err))
}
return info, nil
}View on GitHub (pinned to b6b368adc5)
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).
Defensive patterns
Strategy: validation
Validate before calling
// Before trusting Stat output, ensure the proxy echoes the requested version.
// (mirrors the go command's own invariant)
func statEchoes(repo Repo, ctx context.Context, rev string) error {
info, err := repo.Stat(ctx, rev)
if err != nil { return err }
if info.Version != rev { return fmt.Errorf("proxy echoed %s, want %s", info.Version, rev) }
return nil
} Try / catch
if _, err := repo.Stat(ctx, rev); err != nil {
if strings.Contains(err.Error(), "instead of requested version") {
// switch GOPROXY entry or fall back to direct
}
} Prevention
- Pin module versions explicitly.
- Avoid proxies that auto-upgrade patch versions.
When it happens
Trigger: info.Version != rev AND rev == module.CanonicalVersion(rev) AND module.Check(path, rev) == nil. The proxy substituted a different version in its response.
Common situations: 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.
Related errors
- invalid response from proxy %q: %w
- can only use path@version syntax with 'go get' and 'go insta
- syntax error
- ${GoModToolVersion} is required for tool directives in go.mo
- disallowed module version
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/323af472930af75a.
Report an issue: GitHub.