coreybutler/nvm-windows · error

Invalid character(s) found in prerelease %q

Error message

Invalid character(s) found in prerelease %q

What it means

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.

Source

Thrown at src/semver/semver.go:315

	}
	v := &PRVersion{}
	if containsOnly(s, numbers) {
		if hasLeadingZeroes(s) {
			return nil, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s)
		}
		num, err := strconv.ParseUint(s, 10, 64)

		// Might never be hit, but just in case
		if err != nil {
			return nil, err
		}
		v.VersionNum = num
		v.IsNum = true
	} else if containsOnly(s, alphanum) {
		v.VersionStr = s
		v.IsNum = false
	} else {
		return nil, fmt.Errorf("Invalid character(s) found in prerelease %q", s)
	}
	return v, nil
}

// Is pre release version numeric?
func (v *PRVersion) IsNumeric() bool {
	return v.IsNum
}

// Compares PreRelease Versions v to o:
// -1 == v is less than o
// 0 == v is equal to o
// 1 == v is greater than o
func (v *PRVersion) Compare(o *PRVersion) int {
	if v.IsNum && !o.IsNum {
		return -1
	} else if !v.IsNum && o.IsNum {
		return 1

View on GitHub (pinned to 5b18223ca1)

Solutions

  1. Use dot separation for identifier boundaries: 1.2.3-alpha-1 -> 1.2.3-alpha.1
  2. Remove unsupported symbols from the identifier: 'beta_2' -> 'beta2'
  3. Validate prerelease segments against ^[0-9A-Za-z]+$ before parsing

Example fix

// before
v, err := semver.NewVersion("1.2.3-alpha-1")

// after
v, err := semver.NewVersion("1.2.3-alpha.1")
Defensive patterns

Strategy: type-guard

Validate before calling

var prIdent = regexp.MustCompile(`^[0-9A-Za-z]+$`)
func prereleaseOK(pre string) bool {
    for _, id := range strings.Split(pre, ".") {
        if !prIdent.MatchString(id) { return false }
    }
    return true
}

Type guard

func isSemverPrerelease(s string) bool {
    for _, id := range strings.Split(s, ".") {
        if !regexp.MustCompile(`^[0-9A-Za-z]+$`).MatchString(id) { return false }
    }
    return true
}

Prevention

When it happens

Trigger: 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].

Common situations: Prerelease strings built by concatenating label and build number with a separator ('rc-1', 'nightly#42'), or versions imported from non-semver tag schemes.

Understand the failure class

Related errors


AI-assisted analysis of coreybutler/nvm-windows@5b18223ca1 (2026-08-15). Data as JSON: /api/errors/bc5005b43c018d47. Report an issue: GitHub.