moeru-ai/airi · error
Invalid semver: ${version}
Error message
Invalid semver: ${version} What it means
encodeNumericVersion encodes a semver string into VSCE-compatible numeric-only patch form for the VS Code marketplace. It throws 'Invalid semver' when the input does not match the strict regex ^major.minor.patch(-prerelease)?$, case-insensitive. Leading 'v', missing patch component, build metadata, or non-numeric components all fail.
Source
Thrown at integrations/vscode/vscode-airi/scripts/shared.ts:50
json.version = originalVersion
await writeFile(new URL('../package.json', import.meta.url), `${JSON.stringify(json, null, 2)}\n`, 'utf-8')
},
}
}
// NOTICE: VSCE rejects prerelease identifiers, so we encode stage+sequence into a numeric-only patch bucket:
// encodedPatch = patch*10000 + stageBucket + sequence.
// stageBucket: alpha=1000, beta=2000, rc=3000, stable=9000.
// Examples:
// 0.8.0-alpha.6 -> 0.8.(0*10000+1000+6)=0.8.1006 (preview=true)
// 0.8.0-beta.1 -> 0.8.2001 (preview=true)
// 0.8.0 -> 0.8.(0*10000+9000)=0.8.9000 (preview=false)
// This keeps ordering: alpha < beta < rc < stable. Unknown prerelease tags default to alpha.
export function encodeNumericVersion(version: string) {
const match = version.match(/^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(-(?<pre>[0-9A-Z.-]+))?$/i)
if (!match || !match.groups)
throw new Error(`Invalid semver: ${version}`)
const major = Number.parseInt(match.groups.major, 10)
const minor = Number.parseInt(match.groups.minor, 10)
const patch = Number.parseInt(match.groups.patch, 10)
const prerelease = match.groups.pre
const multiplier = 10_000
const stageBuckets = {
alpha: 1_000,
beta: 2_000,
rc: 3_000,
stable: 9_000,
} as const
const { stage, sequence } = parsePrerelease(prerelease)
const maxSequence = (multiplier - 1) - stageBuckets[stage]
if (sequence > maxSequence) {
throw new Error(`Prerelease sequence overflow for ${stage}: ${sequence} exceeds limit ${maxSequence}`)View on GitHub (pinned to 27111382b4)
Solutions
- Strip a leading 'v' before calling encodeNumericVersion if the input comes from git tags.
- Ensure the version string has exactly three numeric dot-separated components with an optional -prerelease suffix.
- Validate with a semver library (or this same regex) before invoking the encoder and surface a clearer upstream error.
- Check the package.json/build pipeline that produces the version string.
Example fix
// before
const { version, preview } = encodeNumericVersion(rawVersion)
// after
const cleaned = rawVersion.replace(/^v/i, '')
if (!/^(\d+)\.(\d+)\.(\d+)(-[0-9A-Z.-]+)?$/i.test(cleaned)) {
throw new Error(`Version is not valid semver (major.minor.patch[-pre]): ${rawVersion}`)
}
const { version, preview } = encodeNumericVersion(cleaned) Defensive patterns
Strategy: validation
Validate before calling
const SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?$/
function assertSemver(version: string) {
const v = version.replace(/^v/i, '')
if (!SEMVER_RE.test(v)) {
throw new Error(`Not a valid semver string: ${version}`)
}
return v
} Type guard
function isSemverLike(version: unknown): version is string {
return typeof version === 'string'
&& /^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$/.test(version.replace(/^v/i, ''))
} Try / catch
try {
return encodeNumericVersion(raw.replace(/^v/i, ''))
}
catch (err) {
throw new Error(`Cannot encode version for VSCE: ${(err as Error).message}`)
} Prevention
- Strip a leading 'v' from git-tag-derived versions before encoding.
- Run package.json version through a semver library before passing to encodeNumericVersion.
- Assert the version in CI before publishing.
When it happens
Trigger: Passing 'v1.2.3' (leading v), '1.2' (no patch), '1.2.3.4' (extra component), '1.2.3+build' (build metadata not in regex), '' (empty), or any value where major/minor/patch are non-numeric.
Common situations: package.json version was edited manually and malformed; a git tag like 'v0.8.0' is passed verbatim without stripping the v; an external release tool emits a non-semver version string into the encode step.
Related errors
- Prerelease sequence overflow for ${stage}: ${sequence} excee
- Prerelease sequence must be non-negative: ${sequence}
- Invalid Godot stage scene input payload.
- Godot stage exported binary not found. Expected at: ${join(p
- Workflow error: ${errorBody.slice(0, 200)}
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/b89e76ac0f91016d.
Report an issue: GitHub.