{"record":{"id":"f5e71fbe487c1d27","repo":"coreybutler/nvm-windows","slug":"invalid-character-s-found-in-patch-number-q","errorCode":null,"errorMessage":"Invalid character(s) found in patch number %q","messagePattern":"Invalid character\\(s\\) found in patch number %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/semver/semver.go","lineNumber":236,"sourceCode":"\tvar subVersionIndex int\n\tif preIndex != -1 && buildIndex == -1 {\n\t\tsubVersionIndex = preIndex\n\t} else if preIndex == -1 && buildIndex != -1 {\n\t\tsubVersionIndex = buildIndex\n\t} else if preIndex == -1 && buildIndex == -1 {\n\t\tsubVersionIndex = len(parts[2])\n\t} else {\n\t\t// if there is no actual pr version but a hyphen inside the build meta data\n\t\tif buildIndex < preIndex {\n\t\t\tsubVersionIndex = buildIndex\n\t\t\tpreIndex = -1 // Build meta data before preIndex found implicates there are no prerelease versions\n\t\t} else {\n\t\t\tsubVersionIndex = preIndex\n\t\t}\n\t}\n\n\tif !containsOnly(parts[2][:subVersionIndex], numbers) {\n\t\treturn nil, fmt.Errorf(\"Invalid character(s) found in patch number %q\", parts[2][:subVersionIndex])\n\t}\n\tif hasLeadingZeroes(parts[2][:subVersionIndex]) {\n\t\treturn nil, fmt.Errorf(\"Patch number must not contain leading zeroes %q\", parts[2][:subVersionIndex])\n\t}\n\tpatch, err := strconv.ParseUint(parts[2][:subVersionIndex], 10, 64)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tv := &Version{}\n\tv.Major = major\n\tv.Minor = minor\n\tv.Patch = patch\n\n\t// There are PreRelease versions\n\tif preIndex != -1 {\n\t\tvar preRels string\n\t\tif buildIndex != -1 {\n\t\t\tpreRels = parts[2][subVersionIndex+1 : buildIndex]","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/coreybutler/nvm-windows/blob/5b18223ca19ff50d707f35410dbc6bd440a9f74d/src/semver/semver.go#L218-L254","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nv, err := semver.NewVersion(\"1.2.x\")\n\n// after\nv, err := semver.NewVersion(\"1.2.0\")\n// or normalize:\ns := strings.TrimPrefix(strings.TrimSpace(raw), \"v\")\nv, err := semver.NewVersion(s)","handlingStrategy":"type-guard","validationCode":"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.]+)?$`)\nfunc isParsable(v string) bool { return semverCore.MatchString(strings.TrimSpace(v)) }","typeGuard":"func isStrictSemver(v string) bool {\n    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))\n}","tryCatchPattern":"if _, err := semver.NewVersion(input); err != nil {\n    if strings.Contains(err.Error(), \"Invalid character(s) found in patch\") {\n        input = sanitizeVersion(input) // strip junk, retry with cleaned string\n    }\n}","preventionTips":["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"],"tags":["semver","parsing","validation","nvm-windows"],"backgroundTag":null,"analyzedSha":"5b18223ca19ff50d707f35410dbc6bd440a9f74d","analyzedAt":"2026-08-15T10:06:51.428Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}