{"record":{"id":"1d01fc6f6ce7c16c","repo":"halo-dev/halo","slug":"esm-ui-provider-output-is-missing-its-entry-asset","errorCode":null,"errorMessage":"ESM UI provider output is missing its entry asset ${entryFile}.","messagePattern":"ESM UI provider output is missing its entry asset (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"ui/packages/ui-plugin-bundler-kit/src/rsbuild-esm.ts","lineNumber":59,"sourceCode":"      );\n\n      api.processAssets(\n        { stage: \"summarize\" },\n        async ({ assets, compilation, sources }) => {\n          const entryFiles =\n            compilation.entrypoints.get(\"main\")?.getFiles() || [];\n          const entryScripts = entryFiles.filter((fileName) =>\n            fileName.endsWith(\".js\")\n          );\n          if (entryScripts.length !== 1) {\n            throw new Error(\n              \"ESM UI provider output must contain exactly one entry JavaScript file.\"\n            );\n          }\n          const entryFile = entryScripts[0];\n          const entry = assets[entryFile];\n          if (!entry) {\n            throw new Error(\n              `ESM UI provider output is missing its entry asset ${entryFile}.`\n            );\n          }\n          const entryCode = entry.source().toString();\n          await validator.validateSource(entryCode, entryFile);\n          if (\n            !/\\bexport\\s+default\\b/.test(entryCode) &&\n            !/\\bexport\\s*\\{[^}]*\\bdefault\\b[^}]*\\}/s.test(entryCode)\n          ) {\n            throw new Error(\n              \"ESM UI provider output must expose a default PluginModule export.\"\n            );\n          }\n          const entryStyles =\n            compilation.entrypoints\n              .get(\"main\")\n              ?.getFiles()\n              .filter((fileName) => fileName.endsWith(\".css\")) || [];","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/ui/packages/ui-plugin-bundler-kit/src/rsbuild-esm.ts#L41-L77","documentation":"normalizeResourcePath throws this IllegalArgumentException when the entry/style path, after backslash-to-slash conversion, has no text. Caught upstream and surfaced as ClassifiedProvider.invalid.","triggerScenarios":"ui-plugin.json's entry or style is an empty string or whitespace only.","commonSituations":"Manifest templated with an unset variable producing \"\"; leftover placeholder cleared to blank.","solutions":["Provide a non-empty relative path for entry (and style) in ui-plugin.json.","Drop the optional style field entirely if no stylesheet is needed.","Assert non-blank paths in the plugin build before packaging."],"exampleFix":"// before\n{\n  \"format\": \"esm\",\n  \"entry\": \"\"\n}\n// after\n{\n  \"format\": \"esm\",\n  \"entry\": \"index.js\"\n}","handlingStrategy":"validation","validationCode":"String p = manifest.path(\"entry\").asText();\nif (!StringUtils.hasText(p.replace('\\\\', '/').trim())) {\n    throw new IllegalStateException(\"ui-plugin.json entry must not be blank\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never leave entry as an empty string.","Omit optional style when there is no stylesheet.","Assert non-blank in CI."],"tags":["plugin","ui-bundle","esm","provider-manifest","validation"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}