halo-dev/halo · warning · Error
ESM provider manifest entry is required.
Error message
ESM provider manifest entry is required.
What it means
Inside UiPluginBundleServiceImpl.readManifest the parsed ui-plugin.json root must be a JSON object; if it is an array, string, number, or scalar this IllegalArgumentException is thrown. It is caught one frame up and converted into ClassifiedProvider.invalid(candidate, message), so the provider is marked invalid rather than crashing the bundle build — the plugin's ESM UI bundle will not be served.
Source
Thrown at ui/packages/ui-plugin-bundler-kit/src/provider-manifest.ts:29
export function validateEsmProviderManifest(
value: unknown
): EsmProviderManifest {
if (!isRecord(value)) {
throw new Error("ESM provider manifest must be an object.");
}
const keys = Object.keys(value).sort();
if (
!keys.includes("entry") ||
!keys.includes("format") ||
keys.some((key) => !["entry", "format", "style"].includes(key)) ||
value.format !== "esm"
) {
throw new Error(
'ESM provider manifest must contain format, entry, and optional style only with format "esm".'
);
}
if (typeof value.entry !== "string") {
throw new Error("ESM provider manifest entry is required.");
}
const manifest: EsmProviderManifest = {
format: "esm",
entry: normalizeProviderResourcePath(value.entry),
};
if ("style" in value) {
if (typeof value.style !== "string") {
throw new Error("ESM provider manifest style must be a string.");
}
manifest.style = normalizeProviderResourcePath(value.style);
}
return manifest;
}
export function normalizeProviderResourcePath(resourcePath: string) {
const normalizedSlashes = resourcePath.replaceAll("\\", "/");
if (
!normalizedSlashes ||View on GitHub (pinned to d2f5165f9c)
Solutions
- Make ui-plugin.json a single JSON object with format, entry, and optional style fields.
- Re-run the plugin scaffold/manifest generator to regenerate a well-formed ui-plugin.json.
- Lint the JSON in CI before packaging the plugin jar.
Example fix
// before — ui-plugin.json
["module.js"]
// after
{
"format": "esm",
"entry": "module.js"
} Defensive patterns
Strategy: validation
Validate before calling
// Validate ui-plugin.json shape before packaging the jar.
JsonNode n = JSON_MAPPER.readTree(uiPluginJsonFile);
if (!n.isObject()) {
throw new IllegalStateException("ui-plugin.json must be a JSON object");
} Type guard
static boolean isManifestObject(JsonNode n) { return n != null && n.isObject(); } Prevention
- Lint ui-plugin.json with a JSON schema in plugin CI.
- Generate the manifest with the official scaffold rather than by hand.
- Open ui-plugin.json in an editor with JSON validation before publish.
When it happens
Trigger: A plugin ships a console/ui-plugin.json whose top-level JSON value is not an object (e.g. a bare array of providers or a string), read when the UI bundle service classifies the provider.
Common situations: Author hand-edits ui-plugin.json into an array; build tool emits a JSON array instead of an object; truncation/corruption leaving a scalar.
Related errors
- ESM provider manifest style must be a string.
- Provider resource path must be provider-root-relative: ${res
- Provider resource path escapes its root: ${resourcePath}.
- ESM UI provider output is missing its entry asset ${entryFil
- ESM UI provider output must contain exactly one entry JavaSc
AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14).
Data as JSON: /api/errors/b14128c9a4dee4a5.
Report an issue: GitHub.