browsh-org/browsh · error
VersionOrdinal: invalid version
Error message
VersionOrdinal: invalid version
What it means
versionOrdinal converts a dotted Firefox version string into a comparable ordinal by appending bytes and incrementing separators. When a numeric segment exceeds 255 (or the string is otherwise malformed such that the running byte value would overflow maxByte), it panics with 'VersionOrdinal: invalid version'. It guards the algorithm's byte-per-segment assumption.
Source
Thrown at interfacer/src/browsh/firefox.go:150
vo := make([]byte, 0, len(version)+8)
j := -1
for i := 0; i < len(version); i++ {
b := version[i]
if '0' > b || b > '9' {
vo = append(vo, b)
j = -1
continue
}
if j == -1 {
vo = append(vo, 0x00)
j = len(vo) - 1
}
if vo[j] == 1 && vo[j+1] == '0' {
vo[j+1] = b
continue
}
if vo[j]+1 > maxByte {
panic("VersionOrdinal: invalid version")
}
vo = append(vo, b)
vo[j]++
}
return string(vo)
}
// Start Firefox via the `web-ext` CLI tool. This is for development and testing,
// because I haven't been able to recreate the way `web-ext` injects an unsigned
// extension.
func startWERFirefox() {
slog.Info("Attempting to start headless Firefox with `web-ext`")
if IsConnectedToWebExtension {
Shutdown(errors.New("There appears to already be an existing Web Extension connection"))
}
checkIfFirefoxIsAlreadyRunning()
rootDir := Shell("git rev-parse --show-toplevel")
args := []string{View on GitHub (pinned to 499ef386d4)
Solutions
- Check the Firefox version string browsh detected (log output) for an unexpected format and correct the source of the version (registry value, `firefox --version`).
- Upgrade browsh to a release that handles newer version formats.
- Patch/replace versionOrdinal to parse numeric segments into integers instead of single bytes.
- Pin a Firefox version whose format the current algorithm supports.
Example fix
// before
if vo[j]+1 > maxByte {
panic("VersionOrdinal: invalid version")
}
// after
if seg, err := strconv.Atoi(part); err == nil && seg > 255 {
// compare numerically instead of byte ordinal
return compareNumericSegments(parts, other)
} Defensive patterns
Strategy: validation
Validate before calling
// check version string before browsh processes it
function isSafeVersion(v) {
return /^\d+(\.\d+)*$/.test(v) && v.split('.').every(n => Number(n) <= 255);
}
if (!isSafeVersion(firefoxVersion)) console.warn('Version unsupported by ordinal comparison'); Type guard
function isValidVersionString(v) {
return typeof v === 'string' && /^\d+(\.\d+)*$/.test(v) &&
v.split('.').every(seg => parseInt(seg, 10) >= 0 && parseInt(seg, 10) <= 255);
} Prevention
- Log the detected Firefox version and sanity-check its format before upgrades.
- Keep browsh updated to support current Firefox version formats.
- Pin known-good Firefox versions in CI/environments.
- On Windows, verify the registry CurrentVersion value is a plain dotted-numeric string.
When it happens
Trigger: ensureFirefoxVersion passes a version string whose segment value exceeds 255, or a non-numeric/unexpectedly formatted version string that corrupts the ordinal computation, into versionOrdinal.
Common situations: A future Firefox version with a major number above 255 (unlikely but possible) or an unusual segment; a nightly/beta or fork reporting versions like '100.0.1' plus unexpected suffixes; a registry CurrentVersion value with unexpected format on Windows.
Related errors
- A headless Firefox is already running
- Firefox binary not found:
- There appears to already be an existing Web Extension connec
- Failed to connect to Firefox's Marionette within 30 seconds
- Installed Firefox version is too old. Firefox 57 or newer i
AI-assisted analysis of browsh-org/browsh@499ef386d4 (2026-09-02).
Data as JSON: /api/errors/323f0eebb4411f54.
Report an issue: GitHub.