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

  1. Supply a canonical semver token with the `v` prefix (`v1.2.3`).
  2. For an interval, use the `[v1.0.0,v2.0.0]` bracket form.
  3. 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

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


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