{"record":{"id":"bc5005b43c018d47","repo":"coreybutler/nvm-windows","slug":"invalid-character-s-found-in-prerelease-q","errorCode":null,"errorMessage":"Invalid character(s) found in prerelease %q","messagePattern":"Invalid character\\(s\\) found in prerelease %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/semver/semver.go","lineNumber":315,"sourceCode":"\t}\n\tv := &PRVersion{}\n\tif containsOnly(s, numbers) {\n\t\tif hasLeadingZeroes(s) {\n\t\t\treturn nil, fmt.Errorf(\"Numeric PreRelease version must not contain leading zeroes %q\", s)\n\t\t}\n\t\tnum, err := strconv.ParseUint(s, 10, 64)\n\n\t\t// Might never be hit, but just in case\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv.VersionNum = num\n\t\tv.IsNum = true\n\t} else if containsOnly(s, alphanum) {\n\t\tv.VersionStr = s\n\t\tv.IsNum = false\n\t} else {\n\t\treturn nil, fmt.Errorf(\"Invalid character(s) found in prerelease %q\", s)\n\t}\n\treturn v, nil\n}\n\n// Is pre release version numeric?\nfunc (v *PRVersion) IsNumeric() bool {\n\treturn v.IsNum\n}\n\n// Compares PreRelease Versions v to o:\n// -1 == v is less than o\n// 0 == v is equal to o\n// 1 == v is greater than o\nfunc (v *PRVersion) Compare(o *PRVersion) int {\n\tif v.IsNum && !o.IsNum {\n\t\treturn -1\n\t} else if !v.IsNum && o.IsNum {\n\t\treturn 1","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/coreybutler/nvm-windows/blob/5b18223ca19ff50d707f35410dbc6bd440a9f74d/src/semver/semver.go#L297-L333","documentation":"Semver parse error from NewPRVersion(): a prerelease identifier contains characters that are neither all-numeric nor all-alphanumeric — i.e. it fails both containsOnly(numbers) and containsOnly(alphanum). Prerelease identifiers must be either purely numeric or purely alphanumeric-hyphen allowed? No: per this strict implementation, mixed strings like 'alpha-1' or 'beta_2' fail because '-' and '_' are not in the allowed set for a single identifier.","triggerScenarios":"semver.NewVersion(\"1.2.3-alpha-1\"), \"1.2.3-beta_2\", or any prerelease identifier mixing digits with symbols outside [0-9A-Za-z].","commonSituations":"Prerelease strings built by concatenating label and build number with a separator ('rc-1', 'nightly#42'), or versions imported from non-semver tag schemes.","solutions":["Use dot separation for identifier boundaries: 1.2.3-alpha-1 -> 1.2.3-alpha.1","Remove unsupported symbols from the identifier: 'beta_2' -> 'beta2'","Validate prerelease segments against ^[0-9A-Za-z]+$ before parsing"],"exampleFix":"// before\nv, err := semver.NewVersion(\"1.2.3-alpha-1\")\n\n// after\nv, err := semver.NewVersion(\"1.2.3-alpha.1\")","handlingStrategy":"type-guard","validationCode":"var prIdent = regexp.MustCompile(`^[0-9A-Za-z]+$`)\nfunc prereleaseOK(pre string) bool {\n    for _, id := range strings.Split(pre, \".\") {\n        if !prIdent.MatchString(id) { return false }\n    }\n    return true\n}","typeGuard":"func isSemverPrerelease(s string) bool {\n    for _, id := range strings.Split(s, \".\") {\n        if !regexp.MustCompile(`^[0-9A-Za-z]+$`).MatchString(id) { return false }\n    }\n    return true\n}","tryCatchPattern":null,"preventionTips":["Split compound prerelease labels with dots (alpha.1) instead of separators like '-' or '_'","Reject versions from external tag schemes at the boundary and normalize them"],"tags":["semver","prerelease","parsing","validation"],"backgroundTag":null,"analyzedSha":"5b18223ca19ff50d707f35410dbc6bd440a9f74d","analyzedAt":"2026-08-15T10:06:51.428Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}