{"record":{"id":"89ca177690df9732","repo":"halo-dev/halo","slug":"invalid-target-halo-version-targethaloversion","errorCode":null,"errorMessage":"Invalid target Halo version: ${targetHaloVersion}.","messagePattern":"Invalid target Halo version: (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ui/packages/ui-plugin-bundler-kit/src/runtime-snapshot.ts","lineNumber":85,"sourceCode":"  }\n\n  const packages = Object.fromEntries(\n    SHARED_PACKAGE_ROOTS.map((root) => [\n      root,\n      validateSnapshotEntry(root, snapshotPackages[root]),\n    ])\n  ) as Record<SharedPackageRoot, HostRuntimeSnapshotEntry>;\n\n  return deepFreeze({ haloVersion: value.haloVersion, packages });\n}\n\nexport function selectHaloHostRuntimeSnapshot(\n  targetHaloVersion: string,\n  snapshots: readonly HaloHostRuntimeSnapshot[] = HALO_HOST_RUNTIME_SNAPSHOTS\n) {\n  const target = parse(targetHaloVersion);\n  if (!target) {\n    throw new Error(`Invalid target Halo version: ${targetHaloVersion}.`);\n  }\n\n  const eligible = snapshots\n    .filter(\n      (snapshot) =>\n        lte(snapshot.haloVersion, target.version) ||\n        (target.prerelease.length > 0 &&\n          snapshot.haloVersion ===\n            `${target.major}.${target.minor}.${target.patch}`)\n    )\n    .sort((left, right) => compare(right.haloVersion, left.haloVersion));\n  const snapshot = eligible[0];\n  if (!snapshot) {\n    throw new Error(\n      `No ESM host runtime snapshot is available for Halo ${targetHaloVersion}. ` +\n        \"Update @halo-dev/ui-plugin-bundler-kit or select IIFE output.\"\n    );\n  }","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/ui/packages/ui-plugin-bundler-kit/src/runtime-snapshot.ts#L67-L103","documentation":"When the plugin path is a directory, getManifestPath iterates the DevelopmentPluginClasspath classes directories; if none contains plugin.yaml (DEFAULT_PROPERTIES_FILE_NAME) it throws this PluginRuntimeException. Surfaces during install/upgrade/reload of an unpacked plugin.","triggerScenarios":"Installing a plugin from a directory whose classes directories (e.g. classes/) do not contain a plugin.yaml file.","commonSituations":"Development mode where plugin.yaml was not copied to the classes output; wrong directory layout; building a directory distribution that omits the descriptor.","solutions":["Place plugin.yaml under the classes directory inside the plugin directory (e.g. <pluginDir>/classes/plugin.yaml).","Re-run the dev build/copy step that stages plugin.yaml into classes.","Package the plugin as a jar instead and install the jar."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// For directory installs, ensure plugin.yaml is under a classes dir.\nPath dir = pluginPath;\nboolean found = new DevelopmentPluginClasspath().getClassesDirectories().stream()\n    .anyMatch(loc -> Files.exists(dir.resolve(loc).resolve(\"plugin.yaml\")));\nif (!found) {\n    throw new IllegalStateException(\"No plugin.yaml under any classes directory\");\n}","typeGuard":null,"tryCatchPattern":"pluginService.install(path)\n    .onErrorResume(PluginRuntimeException.class,\n        e -> Mono.error(new BusinessException(\"Directory missing plugin.yaml: \" + e.getMessage())))","preventionTips":["In dev mode, copy plugin.yaml into the classes output directory.","Prefer installing the packaged jar over a raw directory.","Verify the directory layout matches the DevelopmentPluginClasspath convention."],"tags":["plugin","manifest","install","development","packaging"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}