golang/go · error
%s: argument must be a clean package path
Error message
%s: argument must be a clean package path
What it means
Thrown by the Go command's package@version install workflow (e.g. `go install pkg@v1.0.0`). After stripping the `@version` suffix, the remaining path `p` is rejected when `pathpkg.Clean(p) != p`, i.e. the path is not in canonical form. The command requires a clean import path because non-canonical forms (redundant slashes, stray `.`/`..` segments) make module resolution ambiguous.
Source
Thrown at src/cmd/go/internal/load/pkg.go:3411
}
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.
//
// If multiple modules match the first argument, accept the longest match
// (first result). It's possible this module won't provide packages named by
// later arguments, and other modules would. Let's not try to be too
// magical though.
allowed := ld.CheckAllowed
if modload.IsRevisionQuery(firstPath, version) {View on GitHub (pinned to b6b368adc5)
Solutions
- Remove redundant `/`, leading/trailing separators, and `.`/`..` segments from the path portion before `@version`.
- If constructing the argument in code, run `path.Clean(p)` and assert it equals `p` before appending `@version`.
- Use the canonical module root path exactly as it appears in the module's go.mod `module` directive.
Example fix
// before go install example.com/foo/../bar@v1.0.0 // after go install example.com/bar@v1.0.0
Defensive patterns
Strategy: validation
Validate before calling
import "path"
func cleanPackageArg(p, version string) (string, error) {
if path.Clean(p) != p {
return "", fmt.Errorf("path %q is not clean; use %q", p, path.Clean(p))
}
return p + "@" + version, nil
} Prevention
- Never build package@version strings by raw concatenation; clean the path first with path.Clean.
- Pull module paths directly from the module's published go.mod rather than typing them.
- Add a lint step in build scripts that rejects non-canonical import paths.
When it happens
Trigger: Running `go install` or `go get pkg@version` where the path portion contains double slashes, leading/trailing slashes, or `.`/`..` segments, e.g. `go install example.com/foo//bar@v1.0.0` or `go install example.com/./pkg@latest`.
Common situations: Copy-pasting a path with stray slashes; building the argument string programmatically without cleaning it; concatenating path fragments that introduce redundant separators.
Related errors
- %s: argument must not be a package in the standard library
- %s: %w
- package %s not provided by module %s
- package %s provided by module %s@%s All packages must be pr
- module requires Go ${p.Module.GoVersion} or later
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/efe90850bbc07b6b.
Report an issue: GitHub.