koala73/worldmonitor · error · Error
no module entry script in ${dashboardPath} — run: ${BUILD_CO
Error message
no module entry script in ${dashboardPath} — run: ${BUILD_COMMANDS.dashboard} What it means
deferredDashboardAppDependencies locates the dashboard's `<script type="module" src=...>` entry in dashboard.html to inspect its loader for the deferred App chunk import. If no module entry script tag (or an src outside assets/) is found, it throws with a hint to run the dashboard build. This keeps the preload-dependency measurement anchored to a real production entry chunk.
Solutions
- Run BUILD_COMMANDS.dashboard to regenerate a production dashboard.html with a hashed module entry
- Inspect the <script type="module"> tag in dist/dashboard.html and restore it if the template was edited
- Ensure the entry src resolves under assets/ (check Vite base/assetsDir) so assetFileNameFromUrl can extract the file name
- If the HTML shape legitimately changed, update the regex in deferredDashboardAppDependencies
Example fix
<!-- before: template missing module entry --> <!-- no script tag --> <!-- after --> <script type="module" src="/assets/index-abc123.js"></script>
Defensive patterns
Strategy: validation
Validate before calling
const html = readFileSync(join(distDir, 'dashboard.html'), 'utf8');
if (!/<script\b[^>]*type=["']module["'][^>]*src=["'][^"']+\.js["']/i.test(html)) throw new Error('dashboard.html has no module entry script — run the production build'); Type guard
const hasModuleEntry = (html) => /<script\b[^>]*\btype=["']module["'][^>]*\bsrc=["'][^"']+\.js["']/i.test(html);
Try / catch
try {
const deps = deferredDashboardAppDependencies(distDir);
} catch (e) {
if (e.message.includes('no module entry script')) {
console.error('Production dashboard build missing module entry; rebuild.');
process.exitCode = 1;
} else throw e;
} Prevention
- Preserve the `<script type="module" src="...">` tag in the HTML template
- Never strip the type="module" attribute or move the entry outside assets/
- Rebuild the dashboard after any Vite config or template change
- Run budget checks only on fresh production output
When it happens
Trigger: Calling deferredDashboardAppDependencies on dashboard.html lacking a `<script type="module" src=".../assets/*.js">` tag — dev-mode HTML (no hashed module script), HTML where the module script lost its type="module" attribute, or the src URL not under /assets/ so assetFileNameFromUrl returns null.
Common situations: Budget check run before the production build; Vite config switched to a legacy/no-module output; someone hand-edited index.html template and removed or altered the module script tag; regex mismatch after changing attribute order/quotes in the template.
Related errors
- no initial JS assets referenced by ${dashboardPath} — run: $
- ${pagePath} is missing its recent-developments section
- ${pagePath} dropped its frozen intel brief
- ${PRO_HTML_PATH} must carry exactly one dateModified node (f
- cannot read ${dashboardPath} — run: ${BUILD_COMMANDS.dashboa
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15).
Data as JSON: /api/errors/8eebdc39e258771a.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/bundle-budgets.mjs:201
/**
* The asset files Vite preloads for the dashboard entry's deferred
* `import('./App-<hash>.js')`, in preload-list order and including CSS, or
* null when the entry has no such import (App is then in the initial payload).
*
* Vite emits the loader as `P(() => import('./App-x.js')…, __vite__mapDeps([…]))`,
* where the indices point into one `m.f=[…]` table and the list starts with
* the imported chunk itself. Anything that breaks that shape throws: a parser
* that silently measured the wrong list would let the application graph grow
* unseen.
*/
export function deferredDashboardAppDependencies(distDir) {
const { dashboardPath, html } = readDashboardHtml(distDir);
const entryUrl = /<script\b[^>]*\btype=["']module["'][^>]*\bsrc=["']([^"']+\.js(?:[?#][^"']*)?)["']/i
.exec(html)?.[1];
const entryName = entryUrl ? assetFileNameFromUrl(entryUrl) : null;
if (!entryName) {
throw new Error(`no module entry script in ${dashboardPath} — run: ${BUILD_COMMANDS.dashboard}`);
}
const entryPath = join(distDir, 'assets', entryName);
let source;
try {
source = readFileSync(entryPath, 'utf8');
} catch (error) {
throw new Error(`cannot read dashboard entry ${entryPath}: ${error.message}`);
}
const appImport = /import\(\s*["']\.\/(App-[A-Za-z0-9_-]{8}\.js)["']\s*\)/.exec(source);
if (!appImport) return null;
const appFile = appImport[1];
const unsupported = (reason) => new Error(
`${entryPath}: ${reason} for the deferred ./${appFile} import — the Vite loader shape changed; `
+ 'update deferredDashboardAppDependencies in scripts/bundle-budgets.mjs',
);
const afterImport = source.slice(appImport.index + appImport[0].length);View on GitHub (pinned to 7d06c8633d)