stablyai/orca · error · Error

Package version is not valid semver: ${baseVersion}

Error message

Package version is not valid semver: ${baseVersion}

What it means

Thrown by createHourlyBuildVersion() when baseVersion does not match the regex `/^(\d+\.\d+\.\d+)(?:-[0-9A-Za-z.-]+)?$/`. This accepts a stable x.y.z or a prerelease-tagged x.y.z-something, rejecting anything that is not valid semver-ish (build metadata with '+', leading 'v', missing patch, etc.). baseVersion normally comes from package.json's version field (via resolveDevChannelBaseVersion).

Source

Thrown at config/scripts/hourly-build-version.mjs:15

import { execFileSync } from 'node:child_process'
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { formatReleaseTitleTimestamp } from './release-title-timestamp.mjs'
import {
  readPublishedVersionsFromEnv,
  resolveDevChannelBaseVersion
} from './dev-channel-base-version.mjs'

/** `1.4.160-hourly.202607281400` — UTC to the minute, so tags sort chronologically
 *  by semver and every build is uniquely versioned. */
export function createHourlyBuildVersion(baseVersion, date) {
  const match = /^(\d+\.\d+\.\d+)(?:-[0-9A-Za-z.-]+)?$/.exec(baseVersion)
  if (!match) {
    throw new Error(`Package version is not valid semver: ${baseVersion}`)
  }
  if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
    throw new Error('Hourly build timestamp is invalid.')
  }
  const pad = (value, width = 2) => String(value).padStart(width, '0')
  const stamp = [
    pad(date.getUTCFullYear(), 4),
    pad(date.getUTCMonth() + 1),
    pad(date.getUTCDate()),
    pad(date.getUTCHours()),
    pad(date.getUTCMinutes())
  ].join('')
  // Why: drop any -rc.N tail. Keeping it makes every hourly semver-NEWER than the
  // RC it was cut from (1.4.160-rc.3-hourly.X > 1.4.160-rc.3), which would let an
  // ordinary RC-channel check offer untested hourly builds to RC users. Stripping
  // to the base parks hourlies below both rc.N and stable ('hourly' < 'rc'
  // alphabetically), reachable only by an explicit pinned jump.
  return `${match[1]}-hourly.${stamp}`

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Ensure package.json version is valid semver (x.y.z or x.y.z-prerelease): e.g. `1.4.160` or `1.4.160-rc.1`.
  2. If passing a value directly, strip leading 'v' and build metadata ('+...') before calling.
  3. Validate with a semver library before invoking if the source is untrusted.

Example fix

// before
createHourlyBuildVersion('v1.4.0', new Date())  // throws
// after
createHourlyBuildVersion('1.4.0', new Date())
Defensive patterns

Strategy: validation

Validate before calling

import semver from 'semver'
function assertBaseVersion(v: string) {
  if (!semver.valid(v)) throw new Error(`Package version is not valid semver: ${v}`)
}
assertBaseVersion(baseVersion)

Type guard

const isValidBaseVersion = (v: unknown): v is string =>
  typeof v === 'string' && /^(\d+\.\d+\.\d+)(?:-[0-9A-Za-z.-]+)?$/.test(v)

Prevention

When it happens

Trigger: package.json version is malformed (e.g. '1.4', 'v1.4.0', '1.4.0+sha'), or a caller passes a non-semver string into createHourlyBuildVersion directly.

Common situations: A bad manual edit to package.json version, a release tool writing a non-standard version string, or calling the function with a raw git tag/branch name instead of a resolved base version.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/21287bd235e9c5f8. Report an issue: GitHub.