{"record":{"id":"fdce4f3ff8f0e111","repo":"stablyai/orca","slug":"package-version-is-not-valid-semver-baseversion","errorCode":null,"errorMessage":"Package version is not valid semver: ${baseVersion}","messagePattern":"Package version is not valid semver: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/scripts/adhoc-build-version.mjs","lineNumber":26,"sourceCode":"} from './dev-channel-base-version.mjs'\n\n/** Long enough to name a feature, short enough that a picker row stays readable. */\nexport const ADHOC_LABEL_MAX_LENGTH = 32\n\n/**\n * `1.4.160-adhoc.20260728140533` — UTC to the second, so tags sort\n * chronologically by semver and every build is uniquely versioned.\n *\n * Why seconds when hourly uses minutes: hourly runs under a concurrency group and\n * cannot overlap itself. Adhoc builds are dispatched on demand, so two people\n * cutting from different branches in the same minute is ordinary — and a\n * minute-resolution tag would collide and fail the second build after its whole\n * pack-and-notarize run.\n */\nexport function createAdhocBuildVersion(baseVersion, date) {\n  const match = /^(\\d+\\.\\d+\\.\\d+)(?:-[0-9A-Za-z.-]+)?$/.exec(baseVersion)\n  if (!match) {\n    throw new Error(`Package version is not valid semver: ${baseVersion}`)\n  }\n  if (!(date instanceof Date) || Number.isNaN(date.getTime())) {\n    throw new Error('Adhoc build timestamp is invalid.')\n  }\n  const pad = (value, width = 2) => String(value).padStart(width, '0')\n  const stamp = [\n    pad(date.getUTCFullYear(), 4),\n    pad(date.getUTCMonth() + 1),\n    pad(date.getUTCDate()),\n    pad(date.getUTCHours()),\n    pad(date.getUTCMinutes()),\n    pad(date.getUTCSeconds())\n  ].join('')\n  // Why: drop any -rc.N tail, same as hourly. Keeping it would make every adhoc\n  // build semver-NEWER than the RC it was cut from, letting an ordinary\n  // RC-channel check offer an unreviewed branch build to RC users. Stripping to\n  // the base parks adhoc below rc.N, hourly, and stable ('adhoc' sorts first\n  // alphabetically), reachable only by an explicit pinned jump.","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/adhoc-build-version.mjs#L8-L44","documentation":"Thrown by createAdhocBuildVersion when baseVersion does not match ^(\\d+\\.\\d+\\.\\d+)(?:-[0-9A-Za-z.-]+)?$. The adhoc version builder strips any prerelease tail and re-stamps the base with -adhoc.<UTC-to-the-second>, so it requires a valid semver core (major.minor.patch) plus an optional prerelease it can safely discard.","triggerScenarios":"package.json version is empty, a non-semver string like 'dev', or a VCS-resolved version; resolveDevChannelBaseVersion returned a malformed value because no published RC version was found and the fallback path produced garbage.","commonSituations":"Branch where package.json was temporarily set to a placeholder version; an env-driven version stamp produced something like '0.0.0-custom+sha'; the workflow's published-versions env input was empty and resolveDevChannelBaseVersion fell back to an unparseable string.","solutions":["Check package.json version and set it to a valid MAJOR.MINOR.PATCH (optionally with a prerelease).","If the bad value came from resolveDevChannelBaseVersion, inspect the ORCA_PUBLISHED_VERSIONS env / workflow output it reads from and ensure at least one valid RC version is present.","Add a unit test asserting createAdhocBuildVersion only ever receives output of resolveDevChannelBaseVersion validated by the same regex.","Surface a clearer error in resolveDevChannelBaseVersion so the failure points at the upstream source rather than the regex here."],"exampleFix":"// before\n// package.json: \"version\": \"dev\"\n// node config/scripts/adhoc-build-version.mjs\n// -> 'Package version is not valid semver: dev'\n\n// after\n// package.json: \"version\": \"1.4.160-rc.1\"\n// node config/scripts/adhoc-build-version.mjs\n// -> version=1.4.160-adhoc.20260728140533","handlingStrategy":"validation","validationCode":"const SEMVER_RE = /^(\\d+\\.\\d+\\.\\d+)(?:-[0-9A-Za-z.-]+)?$/\n\nfunction assertValidBaseVersion(baseVersion) {\n  if (!SEMVER_RE.test(baseVersion)) {\n    throw new Error(`Refusing to build adhoc version: '${baseVersion}' is not semver. Check package.json version.`)\n  }\n}\n// assertValidBaseVersion(baseVersion) before createAdhocBuildVersion","typeGuard":"function isValidBaseVersion(value) {\n  return typeof value === 'string' && /^(\\d+\\.\\d+\\.\\d+)(?:-[0-9A-Za-z.-]+)?$/.test(value)\n}","tryCatchPattern":null,"preventionTips":["Keep package.json version always valid semver, even on feature branches (no 'dev' / '0.0.0' placeholders).","Add a CI lint that asserts package.json.version matches the semver regex before any release workflow can run.","Validate resolveDevChannelBaseVersion's output with the same regex at its boundary, so the failure surfaces at the real source."],"tags":["release","semver","adhoc-build","versioning","validation"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}