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

  1. Supply a concrete version: `go install example.com/tool@latest` or `@v1.2.3`.
  2. Check that any shell variable used for the version is non-empty before invoking go install.
  3. 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

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


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/2faae736633f0558. Report an issue: GitHub.