{"record":{"id":"2faae736633f0558","repo":"golang/go","slug":"s-version-must-not-be-empty","errorCode":null,"errorMessage":"%s: version must not be empty","messagePattern":"(.+?): version must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/load/pkg.go","lineNumber":3392,"sourceCode":"// module, but its go.mod file (if it has one) must not contain directives that\n// would cause it to be interpreted differently if it were the main module\n// (replace, exclude).\nfunc PackagesAndErrorsOutsideModule(ld *modload.Loader, ctx context.Context, opts PackageOpts, args []string) ([]*Package, error) {\n\tif !ld.ForceUseModules {\n\t\tpanic(\"modload.ForceUseModules must be true\")\n\t}\n\tif ld.RootMode != modload.NoRoot {\n\t\tpanic(\"modload.RootMode must be NoRoot\")\n\t}\n\n\t// Check that the arguments satisfy syntactic constraints.\n\tvar version string\n\tvar firstPath string\n\tfor _, arg := range args {\n\t\tif i := strings.Index(arg, \"@\"); i >= 0 {\n\t\t\tfirstPath, version = arg[:i], arg[i+1:]\n\t\t\tif version == \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"%s: version must not be empty\", arg)\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\tpatterns := make([]string, len(args))\n\tfor i, arg := range args {\n\t\tp, found := strings.CutSuffix(arg, \"@\"+version)\n\t\tif !found {\n\t\t\treturn nil, fmt.Errorf(\"%s: all arguments must refer to packages in the same module at the same version (@%s)\", arg, version)\n\t\t}\n\t\tswitch {\n\t\tcase build.IsLocalImport(p):\n\t\t\treturn nil, fmt.Errorf(\"%s: argument must be a package path, not a relative path\", arg)\n\t\tcase filepath.IsAbs(p):\n\t\t\treturn nil, fmt.Errorf(\"%s: argument must be a package path, not an absolute path\", arg)\n\t\tcase search.IsMetaPackage(p):\n\t\t\treturn nil, fmt.Errorf(\"%s: argument must be a package path, not a meta-package\", arg)\n\t\tcase pathpkg.Clean(p) != p:","sourceCodeStart":3374,"sourceCodeEnd":3410,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/load/pkg.go#L3374-L3410","documentation":"Returned by PackagesAndErrorsOutsideModule (line 3392) — the function behind `go install pkg@version`. It scans args for the first containing '@'; everything after the '@' is the version. If that suffix is empty (the arg ends with a bare '@', e.g. `example.com/mod@`), the version is empty and the command rejects it. The arg as written is echoed back.","triggerScenarios":"Running `go install example.com/tool@` (trailing @, no version); a shell variable expanding to empty after the @ (e.g. `go install mod@$VER` with VER unset).","commonSituations":"Typos; CI scripts using an empty version variable; copy-paste from docs where the version placeholder was meant to be filled in.","solutions":["Supply a concrete version: `go install example.com/tool@latest` or `@v1.2.3`.","Check that any shell variable used for the version is non-empty before invoking go install.","Use `@latest` if you simply want the newest release."],"exampleFix":"# before\ngo install example.com/tool@$VERSION   # VERSION unset -> \"...@\"\n# after\nVERSION=v1.4.0; go install example.com/tool@$VERSION","handlingStrategy":"validation","validationCode":"// Ensure the version after '@' is non-empty before invoking go install.\npackage argcheck\n\nimport (\n\t\"errors\"\n\t\"strings\"\n)\n\nfunc VersionNotEmpty(arg string) error {\n\tif i := strings.Index(arg, \"@\"); i >= 0 {\n\t\tif arg[i+1:] == \"\" {\n\t\t\treturn errors.New(\"empty version in: \" + arg)\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["In shell scripts, fail early (`set -u`) so unset version variables do not produce a bare '@'.","Default to `@latest` when a version variable is optional."],"tags":["modules","go-install","cli","toolchain"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}