golang/go · error
%s: version must not be empty
Error message
%s: version must not be empty
What it means
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.
Source
Thrown at src/cmd/go/internal/load/pkg.go:3392
// module, but its go.mod file (if it has one) must not contain directives that
// would cause it to be interpreted differently if it were the main module
// (replace, exclude).
func PackagesAndErrorsOutsideModule(ld *modload.Loader, ctx context.Context, opts PackageOpts, args []string) ([]*Package, error) {
if !ld.ForceUseModules {
panic("modload.ForceUseModules must be true")
}
if ld.RootMode != modload.NoRoot {
panic("modload.RootMode must be NoRoot")
}
// Check that the arguments satisfy syntactic constraints.
var version string
var firstPath string
for _, arg := range args {
if i := strings.Index(arg, "@"); i >= 0 {
firstPath, version = arg[:i], arg[i+1:]
if version == "" {
return nil, fmt.Errorf("%s: version must not be empty", arg)
}
break
}
}
patterns := make([]string, len(args))
for i, arg := range args {
p, found := strings.CutSuffix(arg, "@"+version)
if !found {
return nil, fmt.Errorf("%s: all arguments must refer to packages in the same module at the same version (@%s)", arg, version)
}
switch {
case build.IsLocalImport(p):
return nil, fmt.Errorf("%s: argument must be a package path, not a relative path", arg)
case filepath.IsAbs(p):
return nil, fmt.Errorf("%s: argument must be a package path, not an absolute path", arg)
case search.IsMetaPackage(p):
return nil, fmt.Errorf("%s: argument must be a package path, not a meta-package", arg)
case pathpkg.Clean(p) != p:View on GitHub (pinned to b6b368adc5)
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.
Example fix
# before go install example.com/tool@$VERSION # VERSION unset -> "...@" # after VERSION=v1.4.0; go install example.com/tool@$VERSION
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the version after '@' is non-empty before invoking go install.
package argcheck
import (
"errors"
"strings"
)
func VersionNotEmpty(arg string) error {
if i := strings.Index(arg, "@"); i >= 0 {
if arg[i+1:] == "" {
return errors.New("empty version in: " + arg)
}
}
return nil
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: Typos; CI scripts using an empty version variable; copy-paste from docs where the version placeholder was meant to be filled in.
Related errors
- %s: all arguments must refer to packages in the same module
- %s: argument must be a package path, not a relative path
- %s: argument must be a package path, not an absolute path
- %s: argument must be a package path, not a meta-package
- tool %q is ambiguous; choose one of:
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/2faae736633f0558.
Report an issue: GitHub.