coreybutler/nvm-windows · error
Invalid character(s) found in patch number %q
Error message
Invalid character(s) found in patch number %q
What it means
Semver parse error from the vendored github.com/coreos/go-semver NewVersion(): the patch segment (third dotted component of the version string, before any prerelease/build suffix) contains characters outside [0-9]. It is returned when containsOnly(patch, numbers) fails.
Source
Thrown at src/semver/semver.go:236
var subVersionIndex int
if preIndex != -1 && buildIndex == -1 {
subVersionIndex = preIndex
} else if preIndex == -1 && buildIndex != -1 {
subVersionIndex = buildIndex
} else if preIndex == -1 && buildIndex == -1 {
subVersionIndex = len(parts[2])
} else {
// if there is no actual pr version but a hyphen inside the build meta data
if buildIndex < preIndex {
subVersionIndex = buildIndex
preIndex = -1 // Build meta data before preIndex found implicates there are no prerelease versions
} else {
subVersionIndex = preIndex
}
}
if !containsOnly(parts[2][:subVersionIndex], numbers) {
return nil, fmt.Errorf("Invalid character(s) found in patch number %q", parts[2][:subVersionIndex])
}
if hasLeadingZeroes(parts[2][:subVersionIndex]) {
return nil, fmt.Errorf("Patch number must not contain leading zeroes %q", parts[2][:subVersionIndex])
}
patch, err := strconv.ParseUint(parts[2][:subVersionIndex], 10, 64)
if err != nil {
return nil, err
}
v := &Version{}
v.Major = major
v.Minor = minor
v.Patch = patch
// There are PreRelease versions
if preIndex != -1 {
var preRels string
if buildIndex != -1 {
preRels = parts[2][subVersionIndex+1 : buildIndex]View on GitHub (pinned to 5b18223ca1)
Solutions
- Normalize input to strict semver (MAJOR.MINOR.PATCH with optional -prerelease +build) before parsing
- Strip prefixes like 'v' and any stray whitespace/labels before calling NewVersion
- If loose parsing is needed, pre-validate with a regex and extract the numeric core first
Example fix
// before
v, err := semver.NewVersion("1.2.x")
// after
v, err := semver.NewVersion("1.2.0")
// or normalize:
s := strings.TrimPrefix(strings.TrimSpace(raw), "v")
v, err := semver.NewVersion(s) Defensive patterns
Strategy: type-guard
Validate before calling
var semverCore = regexp.MustCompile(`^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.]+)?(?:\+[0-9A-Za-z.]+)?$`)
func isParsable(v string) bool { return semverCore.MatchString(strings.TrimSpace(v)) } Type guard
func isStrictSemver(v string) bool {
return regexp.MustCompile(`^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-[0-9A-Za-z]+(\.[0-9A-Za-z]+)*)?(\+[0-9A-Za-z]+(\.[0-9A-Za-z]+)*)?$`).MatchString(strings.TrimSpace(v))
} Try / catch
if _, err := semver.NewVersion(input); err != nil {
if strings.Contains(err.Error(), "Invalid character(s) found in patch") {
input = sanitizeVersion(input) // strip junk, retry with cleaned string
}
} Prevention
- Validate version strings against a strict semver regex before parsing
- Trim 'v' prefixes and whitespace from external version inputs
- Reject placeholder segments like x or * early at the API boundary
When it happens
Trigger: Calling semver.NewVersion (directly or via nvm version parsing) with inputs like "1.2.x", "1.2.3a", "1.2.-3", or "1.2.3 beta" where the patch slice up to the first '-'/'+' holds non-numeric characters.
Common situations: Passing version strings from npm registries or user input with unexpected formats (e.g. partial versions, 'latest', suffixed strings); parsing dist-tags or loose versions like "v1.2" style not accepted by this strict parser.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Patch number must not contain leading zeroes %q
- Invalid character(s) found in build meta data %q
- Invalid character(s) found in prerelease %q
- Unrecognized version: "%s"
- NVM_SYMLINK is set to a physical file/directory at %s Please
AI-assisted analysis of coreybutler/nvm-windows@5b18223ca1 (2026-08-15).
Data as JSON: /api/errors/f5e71fbe487c1d27.
Report an issue: GitHub.