stablyai/orca · error · Error
Hourly build number must be a positive integer: ${buildNumbe
Error message
Hourly build number must be a positive integer: ${buildNumber} What it means
formatHourlyReleaseName assembles the human-facing hourly release title (e.g. '1.4.163 • 01 • ... • e698241'), shown verbatim in the GitHub releases list and the in-app build picker. It throws defensively when buildNumber is not a positive integer because the title zero-pads the number with padStart(2,'0') and a non-integer would corrupt the format. The normal path derives buildNumber via nextHourlyBuildNumber (always a positive integer starting at 1), so this guard mainly catches direct or test callers that bypass that derivation.
Source
Thrown at config/scripts/hourly-build-version.mjs:68
const prefix = `${baseVersion} • `
const highest = releaseNames.reduce((max, entry) => {
const name = String(entry ?? '')
if (!name.startsWith(prefix)) {
return max
}
const match = /^(\d+) • /.exec(name.slice(prefix.length))
return match ? Math.max(max, Number(match[1])) : max
}, 0)
return highest + 1
}
/**
* `1.4.163 • 01 • Jul 31, 1:54PM • e698241` — the human-facing release title,
* shown verbatim in both the GitHub releases list and the in-app build picker.
*/
export function formatHourlyReleaseName(version, buildNumber, commit, date) {
if (!Number.isInteger(buildNumber) || buildNumber < 1) {
throw new Error(`Hourly build number must be a positive integer: ${buildNumber}`)
}
return [
version.split('-')[0],
String(buildNumber).padStart(2, '0'),
formatReleaseTitleTimestamp(date),
commit.slice(0, 7)
].join(' • ')
}
// Why the number is derived here rather than passed in: it counts builds of the
// base version, and the base is only known once the published tags have been
// resolved just above. Computing it outside meant numbering against whatever
// version the caller guessed.
export function getHourlyBuildIdentity(now = new Date(), { publishedVersions, releaseNames } = {}) {
const packageJson = JSON.parse(readFileSync(resolve('package.json'), 'utf8'))
const commit = execFileSync('git', ['rev-parse', '--short=12', 'HEAD'], {
encoding: 'utf8'
}).trim()View on GitHub (pinned to 1136503c6a)
Solutions
- Route buildNumber through nextHourlyBuildNumber (or getHourlyBuildIdentity), which always yields a positive integer.
- If calling formatHourlyReleaseName directly, validate/coerce buildNumber with Math.max(1, Math.floor(buildNumber)) before passing it.
- Check the stack to confirm the value did not come from a malformed ORCA_HOURLY_RELEASE_NAMES entry feeding nextHourlyBuildNumber.
Example fix
// before formatHourlyReleaseName(version, buildNumber, commit, date) // after const buildNumber = nextHourlyBuildNumber(base, releaseNames) formatHourlyReleaseName(version, buildNumber, commit, date)
Defensive patterns
Strategy: type-guard
Validate before calling
function isPositiveIntegerBuildNumber(value) {
return Number.isInteger(value) && value >= 1
}
if (!isPositiveIntegerBuildNumber(buildNumber)) {
buildNumber = nextHourlyBuildNumber(base, releaseNames)
} Type guard
function isPositiveBuildNumber(value: unknown): value is number {
return typeof value === 'number' && Number.isInteger(value) && value >= 1
} Prevention
- Always derive buildNumber from nextHourlyBuildNumber or getHourlyBuildIdentity rather than computing it ad hoc.
- In tests, pass explicit positive integers to formatHourlyReleaseName instead of 0 or undefined.
When it happens
Trigger: Calling formatHourlyReleaseName(version, buildNumber, commit, date) with buildNumber of 0, a negative number, a float, NaN, or a non-number. A caller that hand-computes the number or passes a value parsed from an unexpected source can hit it.
Common situations: Unit tests invoking formatHourlyReleaseName directly with a fixture buildNumber of 0 or undefined; a refactor that stops routing through nextHourlyBuildNumber/getHourlyBuildIdentity.
Related errors
- Package version is not valid semver: ${baseVersion}
- Adhoc build timestamp is invalid.
- Adhoc label has no usable characters: ${JSON.stringify(label
- Package version is not valid semver: ${baseVersion}
- Hourly build timestamp is invalid.
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/3b4b1caffd6af6e0.
Report an issue: GitHub.