halo-dev/halo · warning · Error
Provider resource path must be provider-root-relative: ${res
Error message
Provider resource path must be provider-root-relative: ${resourcePath}. What it means
readManifest enforces that ui-plugin.json's format field equals the literal "esm". Any other value (e.g. "iife", "module", "umd") throws this IllegalArgumentException, caught and turned into ClassifiedProvider.invalid. Only ESM providers are supported.
Source
Thrown at ui/packages/ui-plugin-bundler-kit/src/provider-manifest.ts:54
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 ||
normalizedSlashes.startsWith("/") ||
normalizedSlashes.startsWith("//") ||
/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(normalizedSlashes) ||
normalizedSlashes.includes("?") ||
normalizedSlashes.includes("#")
) {
throw new Error(
`Provider resource path must be provider-root-relative: ${resourcePath}.`
);
}
const normalized = path.posix.normalize(normalizedSlashes);
if (normalized === ".." || normalized.startsWith("../")) {
throw new Error(
`Provider resource path escapes its root: ${resourcePath}.`
);
}
return `./${normalized.replace(/^\.\//, "")}`;
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
View on GitHub (pinned to d2f5165f9c)
Solutions
- Set "format": "esm" in ui-plugin.json.
- Rebuild the entry as an ES module (export/import syntax) so the value is truthful.
- If you cannot ship ESM, omit ui-plugin.json entirely to fall back to the legacy bundle path.
Example fix
// before
{
"format": "module",
"entry": "index.js"
}
// after
{
"format": "esm",
"entry": "index.js"
} Defensive patterns
Strategy: validation
Validate before calling
if (!"esm".equals(manifest.path("format").textValue())) {
throw new IllegalStateException("ui-plugin.json format must be 'esm'");
} Prevention
- Build entry bundles as ES modules and set format to 'esm'.
- If you cannot ship ESM, omit ui-plugin.json to use the legacy bundle path.
- Pin the manifest generator that always writes 'esm'.
When it happens
Trigger: A plugin's console/ui-plugin.json sets format to anything other than "esm".
Common situations: Porting a legacy IIFE/UMD bundle and forgetting to flip format; assuming "module" is accepted; case typo like "ESM".
Related errors
- ESM provider manifest entry is required.
- ESM provider manifest style must be a string.
- 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/5a8e7ffd0a6ce35a.
Report an issue: GitHub.