golang/go · error

invalid module version %q

Error message

invalid module version %q

What it means

Thrown by ParsePathVersion (list.go:342) when a module path@version argument has a version string (the part after '@') that begins with '-' or '/'. These prefixes are rejected because they can cause security problems when the version is interpolated into shell commands or filesystem paths (e.g., a version like '-rf' could be interpreted as a command flag). This is a security boundary, not merely a format check.

Source

Thrown at src/cmd/go/internal/modload/list.go:342

	}

	return &modinfo.ModuleError{Err: err.Error()}
}

// ParsePathVersion parses arg expecting arg to be path@version. If there is no
// '@' in arg, found is false, vers is "", and path is arg. This mirrors the
// typical usage of strings.Cut. ParsePathVersion is meant to be a general
// replacement for strings.Cut in module version parsing. If the version is
// invalid, an error is returned. The version is considered invalid if it is
// prefixed with '-' or '/', which can cause security problems when constructing
// commands to execute that use the version.
func ParsePathVersion(arg string) (path, vers string, found bool, err error) {
	path, vers, found = strings.Cut(arg, "@")
	if !found {
		return arg, "", false, nil
	}
	if len(vers) > 0 && (vers[0] == '-' || vers[0] == '/') {
		return "", "", false, fmt.Errorf("invalid module version %q", vers)
	}
	return path, vers, true, nil
}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Sanitize or validate any user-supplied version string before appending it after '@' — reject versions starting with '-' or '/'.
  2. Use canonical semver version strings (e.g. 'v1.2.3') that never start with these characters.
  3. If building tooling on top of ParsePathVersion, wrap it and surface a clear validation error to the end user.

Example fix

// before
version := getUserInput() // e.g. "-rf"
arg := modulePath + "@" + version
path, vers, _, err := modload.ParsePathVersion(arg)

// after — validate first
if version != "" && (version[0] == '-' || version[0] == '/') {
    return fmt.Errorf("invalid version: %q", version)
}
arg := modulePath + "@" + version
Defensive patterns

Strategy: validation

Validate before calling

// Sanitize a user-supplied version before constructing path@version.
func sanitizeVersion(v string) error {
    if v != "" && (v[0] == '-' || v[0] == '/') {
        return fmt.Errorf("invalid module version %q: must not start with '-' or '/'", v)
    }
    return nil
}

Prevention

When it happens

Trigger: Calling 'go get example.com/module@-foo' or 'go get example.com/module@/etc/passwd'. Any code path that calls ParsePathVersion with an arg containing '@' followed by a version starting with '-' or '/'. The function uses strings.Cut to split on '@', then inspects vers[0].

Common situations: User-supplied or script-generated module version strings that are not sanitized before being passed to go commands. Attempting to pass flags after '@' by mistake. Adversarial input in tooling that constructs module@version arguments.

Related errors


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