{"record":{"id":"323f0eebb4411f54","repo":"browsh-org/browsh","slug":"versionordinal-invalid-version","errorCode":null,"errorMessage":"VersionOrdinal: invalid version","messagePattern":"VersionOrdinal: invalid version","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"interfacer/src/browsh/firefox.go","lineNumber":150,"sourceCode":"\tvo := make([]byte, 0, len(version)+8)\n\tj := -1\n\tfor i := 0; i < len(version); i++ {\n\t\tb := version[i]\n\t\tif '0' > b || b > '9' {\n\t\t\tvo = append(vo, b)\n\t\t\tj = -1\n\t\t\tcontinue\n\t\t}\n\t\tif j == -1 {\n\t\t\tvo = append(vo, 0x00)\n\t\t\tj = len(vo) - 1\n\t\t}\n\t\tif vo[j] == 1 && vo[j+1] == '0' {\n\t\t\tvo[j+1] = b\n\t\t\tcontinue\n\t\t}\n\t\tif vo[j]+1 > maxByte {\n\t\t\tpanic(\"VersionOrdinal: invalid version\")\n\t\t}\n\t\tvo = append(vo, b)\n\t\tvo[j]++\n\t}\n\treturn string(vo)\n}\n\n// Start Firefox via the `web-ext` CLI tool. This is for development and testing,\n// because I haven't been able to recreate the way `web-ext` injects an unsigned\n// extension.\nfunc startWERFirefox() {\n\tslog.Info(\"Attempting to start headless Firefox with `web-ext`\")\n\tif IsConnectedToWebExtension {\n\t\tShutdown(errors.New(\"There appears to already be an existing Web Extension connection\"))\n\t}\n\tcheckIfFirefoxIsAlreadyRunning()\n\trootDir := Shell(\"git rev-parse --show-toplevel\")\n\targs := []string{","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/browsh-org/browsh/blob/499ef386d45cd1e2b5457dd04887c017f77b7e27/interfacer/src/browsh/firefox.go#L132-L168","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nif vo[j]+1 > maxByte {\n    panic(\"VersionOrdinal: invalid version\")\n}\n// after\nif seg, err := strconv.Atoi(part); err == nil && seg > 255 {\n    // compare numerically instead of byte ordinal\n    return compareNumericSegments(parts, other)\n}","handlingStrategy":"validation","validationCode":"// check version string before browsh processes it\nfunction isSafeVersion(v) {\n  return /^\\d+(\\.\\d+)*$/.test(v) && v.split('.').every(n => Number(n) <= 255);\n}\nif (!isSafeVersion(firefoxVersion)) console.warn('Version unsupported by ordinal comparison');","typeGuard":"function isValidVersionString(v) {\n  return typeof v === 'string' && /^\\d+(\\.\\d+)*$/.test(v) &&\n    v.split('.').every(seg => parseInt(seg, 10) >= 0 && parseInt(seg, 10) <= 255);\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["versioning","panic","firefox"],"backgroundTag":"invalid-version-string","analyzedSha":"499ef386d45cd1e2b5457dd04887c017f77b7e27","analyzedAt":"2026-09-02T19:05:32.228Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}