golang/go · error
invalid version: %q
Error message
invalid version: %q
What it means
`go mod edit` interval parsing (`parseVersionInterval`): the input is not bracket-delimited, so it is treated as a single version and fails `allowedVersionArg`. Used by flags that accept version intervals (e.g. `-exclude=[low,high]`). A single bare token must still be a valid version string.
Source
Thrown at src/cmd/go/internal/modcmd/edit.go:397
path, version = strings.TrimSpace(before), strings.TrimSpace(after)
}
if err := module.CheckImportPath(path); err != nil {
return path, version, fmt.Errorf("invalid %s path: %v", adj, err)
}
if path != arg && !allowedVersionArg(version) {
return path, version, fmt.Errorf("invalid %s version: %q", adj, version)
}
return path, version, nil
}
// parseVersionInterval parses a single version like "v1.2.3" or a closed
// interval like "[v1.2.3,v1.4.5]". Note that a single version has the same
// representation as an interval with equal upper and lower bounds: both
// Low and High are set.
func parseVersionInterval(arg string) (modfile.VersionInterval, error) {
if !strings.HasPrefix(arg, "[") {
if !allowedVersionArg(arg) {
return modfile.VersionInterval{}, fmt.Errorf("invalid version: %q", arg)
}
return modfile.VersionInterval{Low: arg, High: arg}, nil
}
if !strings.HasSuffix(arg, "]") {
return modfile.VersionInterval{}, fmt.Errorf("invalid version interval: %q", arg)
}
s := arg[1 : len(arg)-1]
before, after, found := strings.Cut(s, ",")
if !found {
return modfile.VersionInterval{}, fmt.Errorf("invalid version interval: %q", arg)
}
low := strings.TrimSpace(before)
high := strings.TrimSpace(after)
if !allowedVersionArg(low) || !allowedVersionArg(high) {
return modfile.VersionInterval{}, fmt.Errorf("invalid version interval: %q", arg)
}
return modfile.VersionInterval{Low: low, High: high}, nil
}View on GitHub (pinned to b6b368adc5)
Solutions
- Supply a canonical semver token with the `v` prefix (`v1.2.3`).
- For an interval, use the `[v1.0.0,v2.0.0]` bracket form.
- Use `latest` only where the flag allows it — `parseVersionInterval` requires concrete versions.
Example fix
// before go mod edit -exclude='foo@[1.0.0,2.0.0]' // after go mod edit -exclude='foo@[v1.0.0,v2.0.0]'
Defensive patterns
Strategy: validation
Validate before calling
// Validate a version or [low,high] interval before `go mod edit`.
func validVersionOrInterval(s string) error {
if strings.HasPrefix(s, "[") {
if !strings.HasSuffix(s, "]") { return errors.New("missing closing ]") }
for _, v := range strings.Split(strings.Trim(s, "[]"), ",") {
if !semver.IsValid(strings.TrimSpace(v)) { return fmt.Errorf("bad bound %q", v) }
}
return nil
}
if !semver.IsValid(s) { return fmt.Errorf("invalid version %q", s) }
return nil
} Prevention
- Use the bracketed `[vLow,vHigh]` form for intervals.
- Ensure both bounds carry the `v` prefix and are valid semver.
- Validate with `semver.IsValid` in scripts that emit `go mod edit` commands.
When it happens
Trigger: `go mod edit -exclude 'foo@1.0.0'` (missing `v`, non-bracketed); `go mod edit -droprequire='foo@random'`; passing a non-semver token where a single version is expected.
Common situations: Same family as 918 but within interval/single-version flags; forgetting `v` prefix; using branch or arbitrary strings.
Related errors
- invalid %s version: %q
- invalid %s path: %v
- module requires Go ${p.Module.GoVersion} or later
- must have SWIG version >= 3.0.6
- %s (in %s): %w
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/3b68fbe7bb41aa4a.
Report an issue: GitHub.