{"record":{"id":"355a859a7e32fd8b","repo":"halo-dev/halo","slug":"esm-ui-provider-output-must-contain-one-entry-with","errorCode":null,"errorMessage":"ESM UI provider output must contain one entry with a default PluginModule export.","messagePattern":"ESM UI provider output must contain one entry with a default PluginModule export\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ui/packages/ui-plugin-bundler-kit/src/vite-esm.ts","lineNumber":46,"sourceCode":"    },\n    async transform(code, id) {\n      if (!id.includes(\"\\0\")) {\n        await validator.validateSource(code, id);\n      }\n    },\n    generateBundle: {\n      order: \"post\",\n      async handler(_outputOptions, bundle) {\n        const chunks = Object.values(bundle).filter(\n          (item) => item.type === \"chunk\"\n        );\n        for (const chunk of chunks) {\n          await validator.validateSource(chunk.code, chunk.fileName);\n        }\n\n        const entries = chunks.filter((chunk) => chunk.isEntry);\n        if (entries.length !== 1 || !entries[0].exports.includes(\"default\")) {\n          throw new Error(\n            \"ESM UI provider output must contain one entry with a default PluginModule export.\"\n          );\n        }\n        const entryStyles = [\n          ...((entries[0] as ViteOutputChunkMetadata).viteMetadata\n            ?.importedCss || []),\n        ].sort();\n        if (entryStyles.length > 1) {\n          throw new Error(\n            \"ESM UI provider output must contain at most one entry stylesheet.\"\n          );\n        }\n        const manifest = validateEsmProviderManifest({\n          format: \"esm\",\n          entry: `./${entries[0].fileName}`,\n          ...(entryStyles[0] ? { style: `./${entryStyles[0]}` } : {}),\n        });\n        this.emitFile({","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/ui/packages/ui-plugin-bundler-kit/src/vite-esm.ts#L28-L64","documentation":"Thrown in the generateBundle hook of the halo:esm-ui-provider Vite plugin when the ESM output does not contain exactly one entry chunk that exports 'default'. The ESM provider contract requires a single entry module with `export default definePluginModule(...)` (a PluginModule) so the host can discover and activate it; zero entries, multiple entries, or a missing default export all violate the contract.","triggerScenarios":"Build output has 0 entry chunks (e.g. build.lib misconfigured, or all chunks are non-entry), 2+ entry chunks (multiple inputs), or exactly one entry whose exports array lacks 'default' (the entry uses named exports only, or exports nothing).","commonSituations":"Vite build.rollupOptions.input lists more than one entry; the entry file calls definePluginModule but assigns it to a const without a default export; a tool/plugin strips the default export; entry is a CSS/asset-only chunk.","solutions":["Ensure the entry file has exactly `export default definePluginModule({ ... })` as its default export.","Configure rollupOptions.input (or build.lib) to a single entry file for the ESM build.","Grep the entry for 'export default' and confirm it is the PluginModule; remove any secondary entry inputs from the ESM build config."],"exampleFix":"// before (entry.ts)\nexport const plugin = definePluginModule({ routes: [] });\n\n// after\nexport default definePluginModule({ routes: [] });","handlingStrategy":"validation","validationCode":"// Pre-build check: ensure the entry file has a single default PluginModule export.\nimport { readFileSync } from \"node:fs\";\nconst entry = readFileSync(\"src/index.ts\", \"utf8\");\nif (!/export\\s+default\\s+definePluginModule/.test(entry)) {\n  throw new Error(\"Entry must `export default definePluginModule(...)`.\");\n}\n// And in vite.config ensure a single input for the esm build.","typeGuard":"function hasSingleDefaultEntry<T extends { isEntry: boolean; exports: readonly string[] }>(chunks: T[]): boolean {\n  const entries = chunks.filter((c) => c.isEntry);\n  return entries.length === 1 && entries[0].exports.includes(\"default\");\n}","tryCatchPattern":null,"preventionTips":["Keep exactly one entry input for the ESM build (build.lib or rollupOptions.input).","Make the entry file's last statement `export default definePluginModule(...)`.","Add a CI grep asserting the default export before building."],"tags":["build","esm","rollup","entry","bundler-kit"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}