halo-dev/halo · critical · Error

${root} snapshot version must be stable semver.

Error message

${root} snapshot version must be stable semver.

What it means

Thrown by validateSnapshotEntry when a host runtime snapshot entry's 'version' field is missing, non-string, or not a stable (non-prerelease) semver. These snapshots are the built-in truth tables shipped inside @halo-dev/ui-plugin-bundler-kit (rawHaloHostRuntimeSnapshots, frozen at module load via validateHaloHostRuntimeSnapshot). The check enforces that every snapshot pins a concrete released Halo dependency version so ESM builds compare against real targets.

Source

Thrown at ui/packages/ui-plugin-bundler-kit/src/runtime-snapshot.ts:186

    newerThanHost: compare(resolvedVersion, parsedHostVersion) > 0,
    differentMajor: resolvedVersion.major !== parsedHostVersion.major,
  };
}

export function isSharedPackageRoot(value: string): value is SharedPackageRoot {
  return sharedPackageRootSet.has(value);
}

function validateSnapshotEntry(
  root: SharedPackageRoot,
  value: unknown
): HostRuntimeSnapshotEntry {
  if (
    !isRecord(value) ||
    typeof value.version !== "string" ||
    !parseStableVersion(value.version)
  ) {
    throw new Error(`${root} snapshot version must be stable semver.`);
  }
  if (
    !Array.isArray(value.exports) ||
    value.exports.length === 0 ||
    value.exports.some(
      (exportName) =>
        typeof exportName !== "string" || !/^[$A-Z_a-z][$\w]*$/.test(exportName)
    ) ||
    new Set(value.exports).size !== value.exports.length
  ) {
    throw new Error(`${root} snapshot exports must be unique identifiers.`);
  }
  if (
    !isRecord(value.runtime) ||
    typeof value.runtime.bridge !== "string" ||
    !/^[a-z0-9-]+$/.test(value.runtime.bridge) ||
    typeof value.runtime.global !== "string" ||
    !/^[$A-Z_a-z][$\w]*$/.test(value.runtime.global) ||

View on GitHub (pinned to d2f5165f9c)

Solutions

  1. If you maintain a fork of the kit, audit runtime-snapshots.ts and ensure every entry.version is a stable MAJOR.MINOR.PATCH (no -alpha/-rc/-beta).
  2. Update @halo-dev/ui-plugin-bundler-kit to the upstream release whose snapshots passed validation.
  3. Reproduce the failing entry by importing HALO_HOST_RUNTIME_SNAPSHOTS in a scratch script and patch the offending version in the snapshot source.

Example fix

// before (runtime-snapshots data)
{ haloVersion: "2.26.0", packages: { vue: { version: "3.4.0-rc.1", ... } } }

// after
{ haloVersion: "2.26.0", packages: { vue: { version: "3.4.0", ... } } }
Defensive patterns

Strategy: validation

Validate before calling

import { parse } from "semver";
function assertStableSnapshotVersion(root: string, version: unknown) {
  const v = typeof version === "string" ? parse(version) : null;
  if (!v || v.prerelease.length > 0) {
    throw new Error(`${root} snapshot version must be stable semver, got ${String(version)}.`);
  }
}

Type guard

import { parse } from "semver";
function isStableVersion(value: unknown): value is string {
  if (typeof value !== "string") return false;
  const v = parse(value);
  return v !== null && v.prerelease.length === 0;
}

Prevention

When it happens

Trigger: Fires at import time of runtime-snapshot.ts when HALO_HOST_RUNTIME_SNAPSHOTS is constructed, if any entry in the bundled runtime-snapshots data has a version like '2.0.0-beta.1', 'latest', '' , or a non-string. Not user-data driven; it guards the kit's own data file.

Common situations: A maintainer edits runtime-snapshots source data and accidentally saves a prerelease tag or a malformed version; a bad merge/rebase into the bundler kit snapshots; a downstream fork that regenerates snapshots without stripping prerelease suffixes.

Related errors


AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14). Data as JSON: /api/errors/323d1814a8f43867. Report an issue: GitHub.