halo-dev/halo · critical · Error

${root} snapshot exports must be unique identifiers.

Error message

${root} snapshot exports must be unique identifiers.

What it means

Thrown by validateSnapshotEntry when a snapshot entry's 'exports' array is missing, empty, contains non-strings or invalid JS identifiers, or has duplicates. The exports list defines which symbols the ESM host exposes for externalization, so each must be a unique valid ECMAScript identifier matching /^[$A-Za-z_][$\w]*$/. Duplicates would collide on the shared global; invalid names would break import rewriting.

Source

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

  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) ||
    (value.runtime.identity !== "singleton" &&
      value.runtime.identity !== "shared")
  ) {
    throw new Error(`${root} snapshot runtime descriptor is invalid.`);
  }
  return {
    version: value.version,
    exports: [...value.exports].sort(),
    runtime: {
      bridge: value.runtime.bridge,
      global: value.runtime.global,

View on GitHub (pinned to d2f5165f9c)

Solutions

  1. Audit the offending root's exports array in runtime-snapshots data: keep only unique identifiers matching /^[$A-Za-z_][$\w]*$/.
  2. Restore the upstream snapshot data file and re-apply only version bumps, not export edits.
  3. Upgrade @halo-dev/ui-plugin-bundler-kit to a release with corrected snapshot exports.

Example fix

// before
exports: ["createApp", "createApp", "h-core"]

// after
exports: ["createApp", "h"]
Defensive patterns

Strategy: validation

Validate before calling

const IDENT = /^[$A-Z_a-z][$\w]*$/;
function validateExports(root: string, exports: unknown) {
  if (!Array.isArray(exports) || exports.length === 0 ||
      exports.some((e) => typeof e !== "string" || !IDENT.test(e)) ||
      new Set(exports).size !== exports.length) {
    throw new Error(`${root} snapshot exports must be unique identifiers.`);
  }
}

Type guard

const IDENT = /^[$A-Z_a-z][$\w]*$/;
function isUniqueIdentifiers(value: unknown): value is string[] {
  return Array.isArray(value) && value.length > 0 &&
    value.every((e) => typeof e === "string" && IDENT.test(e)) &&
    new Set(value).size === value.length;
}

Prevention

When it happens

Trigger: Fires at module load when constructing HALO_HOST_RUNTIME_SNAPSHOTS, if a snapshot entry exports contains entries like 'default-export', '1bad', '', a number, a repeated name, or the array is absent/empty.

Common situations: A forked/regenerated snapshot data file lists a deep import path or a renamed symbol; a hand-edit introduces a typo or duplicate; an export named with a hyphen or leading digit.

Related errors


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