halo-dev/halo · error · Error

Host runtime snapshot must expose exactly: ${SHARED_PACKAGE_

Error message

Host runtime snapshot must expose exactly: ${SHARED_PACKAGE_ROOTS.join(", ")}.

What it means

YamlPluginFinder.unstructuredToPlugin loads the descriptor YAML and requires exactly one YAML document; if the loader returns zero or more than one Unstructured, this PluginRuntimeException is thrown (the file name placeholder is the configured propertiesFileName).

Source

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

  if (
    !isRecord(value) ||
    typeof value.haloVersion !== "string" ||
    !parseStableVersion(value.haloVersion)
  ) {
    throw new Error("Host runtime snapshot haloVersion must be stable semver.");
  }
  if (!isRecord(value.packages)) {
    throw new Error("Host runtime snapshot packages must be an object.");
  }
  const snapshotPackages = value.packages;

  const packageRoots = Object.keys(value.packages).sort();
  const supportedRoots = [...SHARED_PACKAGE_ROOTS].sort();
  if (
    packageRoots.length !== supportedRoots.length ||
    packageRoots.some((root, index) => root !== supportedRoots[index])
  ) {
    throw new Error(
      `Host runtime snapshot must expose exactly: ${SHARED_PACKAGE_ROOTS.join(", ")}.`
    );
  }

  const packages = Object.fromEntries(
    SHARED_PACKAGE_ROOTS.map((root) => [
      root,
      validateSnapshotEntry(root, snapshotPackages[root]),
    ])
  ) as Record<SharedPackageRoot, HostRuntimeSnapshotEntry>;

  return deepFreeze({ haloVersion: value.haloVersion, packages });
}

export function selectHaloHostRuntimeSnapshot(
  targetHaloVersion: string,
  snapshots: readonly HaloHostRuntimeSnapshot[] = HALO_HOST_RUNTIME_SNAPSHOTS
) {

View on GitHub (pinned to d2f5165f9c)

Solutions

  1. Ensure plugin.yaml contains exactly one Plugin document (apiVersion + kind: Plugin).
  2. Remove extra '---' separators and any second document.
  3. Validate that the file is non-empty and parses to a single YAML mapping.

Example fix

// before — two documents
apiVersion: v1alpha1
kind: Plugin
metadata: { name: p1 }
spec: { version: 1.0.0 }
---
apiVersion: v1alpha1
kind: Plugin
metadata: { name: p2 }
// after — single document
apiVersion: v1alpha1
kind: Plugin
metadata: { name: p1 }
spec: { version: 1.0.0 }
Defensive patterns

Strategy: validation

Validate before calling

List<Unstructured> docs = new YamlUnstructuredLoader(resource).load();
if (docs.size() != 1) {
    throw new IllegalStateException("plugin.yaml must contain exactly one Plugin document");
}

Try / catch

pluginService.install(path)
    .onErrorResume(PluginRuntimeException.class,
        e -> Mono.error(new BusinessException("Malformed plugin.yaml: " + e.getMessage())))

Prevention

When it happens

Trigger: plugin.yaml is empty, contains multiple --- separated documents, or holds a non-Plugin document, so the loaded Unstructured list size is not 1.

Common situations: Empty plugin.yaml; concatenating multiple plugin manifests into one file; stray '---' creating extra documents; wrong kind/apiVersion document.

Related errors


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