golang/go · error

%s: argument must be a package path, not a relative path

Error message

%s: argument must be a package path, not a relative path

What it means

Returned by PackagesAndErrorsOutsideModule (line 3405). After stripping the @version suffix, the remaining path is checked: build.IsLocalImport(p) is true when p is `.` or starts with `./` or `../`. `go install pkg@version` cannot target a local relative import because there is no well-defined module/version for it. The arg as written (with @version) is echoed.

Source

Thrown at src/cmd/go/internal/load/pkg.go:3405

	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:
			return nil, fmt.Errorf("%s: argument must be a clean package path", arg)
		case !strings.Contains(p, "...") && search.IsStandardImportPath(p) && modindex.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, p):
			return nil, fmt.Errorf("%s: argument must not be a package in the standard library", arg)
		default:
			patterns[i] = p
		}
	}
	patterns = search.CleanPatterns(patterns)

	// Query the module providing the first argument, load its go.mod file, and
	// check that it doesn't contain directives that would cause it to be
	// interpreted differently if it were the main module.
	//

View on GitHub (pinned to b6b368adc5)

Solutions

  1. For a local package, drop the @version: `go install ./cmd/app`.
  2. For a published package, use its full module path: `go install example.com/app/cmd/app@v1.0.0`.

Example fix

# before
go install ./cmd/app@v1.0.0
# after  (local)
go install ./cmd/app
# after  (remote)
go install example.com/app/cmd/app@v1.0.0
Defensive patterns

Strategy: validation

Validate before calling

// Reject relative imports in `go install pkg@version` args.
package argcheck

import (
	"errors"
	"strings"
)

func NotRelativeImport(arg string) error {
	p := arg
	if i := strings.Index(arg, "@"); i >= 0 {
		p = arg[:i]
	}
	if p == "." || strings.HasPrefix(p, "./") || strings.HasPrefix(p, "../") {
		return errors.New("relative path not allowed with @version: " + arg)
	}
	return nil
}

Prevention

When it happens

Trigger: Running `go install ./cmd/app@v1.0.0`, `go install .@latest`, or `go install ../lib@v2`. The function only accepts fully-qualified module paths.

Common situations: Confusing `go install ./pkg` (local install, no @version allowed) with `go install pkg@version` (remote, must be a module path); muscle memory from `go run ./...`.

Related errors


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