{"record":{"id":"a211582145dc7f30","repo":"golang/go","slug":"invalid-version-q-a21158","errorCode":null,"errorMessage":"invalid version %q","messagePattern":"invalid version %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/modfetch/cache.go","lineNumber":349,"sourceCode":"\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn append([]byte(nil), text...), nil\n}\n\nfunc (r *cachingRepo) Zip(ctx context.Context, dst io.Writer, version string) error {\n\tif gover.IsToolchain(r.path) {\n\t\treturn ErrToolchain\n\t}\n\treturn r.repo(ctx).Zip(ctx, dst, version)\n}\n\n// InfoFile is like Lookup(ctx, path).Stat(version) but also returns the name of the file\n// containing the cached information.\nfunc (f *Fetcher) InfoFile(ctx context.Context, path, version string) (*RevInfo, string, error) {\n\tif !gover.ModIsValid(path, version) {\n\t\treturn nil, \"\", fmt.Errorf(\"invalid version %q\", version)\n\t}\n\n\tif file, info, err := readDiskStat(ctx, path, version); err == nil {\n\t\treturn info, file, nil\n\t}\n\n\tvar info *RevInfo\n\tvar err2info map[error]*RevInfo\n\terr := TryProxies(func(proxy string) error {\n\t\ti, err := f.Lookup(ctx, proxy, path).Stat(ctx, version)\n\t\tif err == nil {\n\t\t\tinfo = i\n\t\t} else {\n\t\t\tif err2info == nil {\n\t\t\t\terr2info = make(map[error]*RevInfo)\n\t\t\t}\n\t\t\terr2info[err] = info\n\t\t}","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modfetch/cache.go#L331-L367","documentation":"Thrown by `Fetcher.InfoFile` when `gover.ModIsValid(path, version)` returns false. InfoFile returns the cached RevInfo (revision info) and the file path containing it. A non-semver version cannot be looked up in the disk cache since the cache path encoding requires a valid version. This is the entry point for getting module revision metadata.","triggerScenarios":"Calling `fetcher.InfoFile(ctx, path, version)` with an invalid version string — not valid semver, not a recognized pseudo-version, not properly formatted for the module path. The version must pass ModIsValid before disk lookup or proxy queries.","commonSituations":"Passing 'latest' or 'HEAD' directly to InfoFile (these are symbolic and must be resolved via Stat first); malformed version strings from user input; bugs in version construction in calling code.","solutions":["Resolve symbolic versions first: call `Lookup(path).Stat(ctx, \"latest\")` to get a concrete version","Validate with `gover.ModIsValid(path, version)` before calling InfoFile","Use the higher-level modfetch.Lookup chain that handles version resolution"],"exampleFix":"// before\ninfo, file, err := f.InfoFile(ctx, path, \"latest\")\n// after\nrevInfo, _ := f.Lookup(ctx, proxy, path).Stat(ctx, \"latest\")\ninfo, file, err := f.InfoFile(ctx, path, revInfo.Version)","handlingStrategy":"validation","validationCode":"import \"golang.org/x/mod/gover\"\n\nfunc safeInfoFile(ctx context.Context, f *modfetch.Fetcher, path, version string) (*modfetch.RevInfo, string, error) {\n    if !gover.ModIsValid(path, version) {\n        return nil, \"\", fmt.Errorf(\"invalid version %q for path %q\", version, path)\n    }\n    return f.InfoFile(ctx, path, version)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Resolve symbolic versions via Stat() before calling InfoFile","Pre-validate versions with gover.ModIsValid","Document that InfoFile expects concrete semver versions, not symbolic ones"],"tags":["go","go-mod","version","validation","internal-api"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}