{"record":{"id":"d3626c33b80c23c0","repo":"koala73/worldmonitor","slug":"cannot-read-dashboardpath-run-build-commands-dashboard-error","errorCode":null,"errorMessage":"cannot read ${dashboardPath} — run: ${BUILD_COMMANDS.dashboard}: ${error.message}","messagePattern":"cannot read (.+?) — run: (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/bundle-budgets.mjs","lineNumber":167,"sourceCode":"\n/** '/assets/main-x.js', 'assets/main-x.js?v=1' -> 'main-x.js'; null outside assets/. */\nfunction assetFileNameFromUrl(url) {\n  const path = url.split(/[?#]/, 1)[0];\n  const marker = path.lastIndexOf('/assets/');\n  const fileName = marker >= 0\n    ? path.slice(marker + '/assets/'.length)\n    : path.startsWith('assets/')\n      ? path.slice('assets/'.length)\n      : null;\n  return fileName && !fileName.includes('/') ? fileName : null;\n}\n\nfunction readDashboardHtml(distDir) {\n  const dashboardPath = join(distDir, 'dashboard.html');\n  try {\n    return { dashboardPath, html: readFileSync(dashboardPath, 'utf8') };\n  } catch (error) {\n    throw new Error(`cannot read ${dashboardPath} — run: ${BUILD_COMMANDS.dashboard}: ${error.message}`);\n  }\n}\n\nexport function initialDashboardAssetNames(distDir) {\n  const { dashboardPath, html } = readDashboardHtml(distDir);\n  const assets = new Set();\n  for (const match of html.matchAll(/(?:src|href)=[\"']([^\"']+\\.js(?:[?#][^\"']*)?)[\"']/gi)) {\n    const fileName = assetFileNameFromUrl(match[1]);\n    if (fileName) assets.add(fileName);\n  }\n  if (assets.size === 0) {\n    throw new Error(`no initial JS assets referenced by ${dashboardPath} — run: ${BUILD_COMMANDS.dashboard}`);\n  }\n  return [...assets].sort();\n}\n\n/**\n * The asset files Vite preloads for the dashboard entry's deferred","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/scripts/bundle-budgets.mjs#L149-L185","documentation":"bundle-budgets.mjs measures the built dashboard bundle sizes by parsing dist/dashboard.html. readDashboardHtml wraps readFileSync of that file; if it cannot be read (missing or unreadable), it throws a remediation-aware error telling the developer to run the dashboard build command first. It exists so budget checks fail with an actionable message instead of a bare ENOENT.","triggerScenarios":"Calling initialDashboardAssetNames or deferredDashboardAppDependencies with a distDir where dist/dashboard.html does not exist (build not run, wrong distDir passed, build output cleaned) or is not readable (permissions).","commonSituations":"CI runs bundle-budget checks before `npm run build:dashboard`; developer checks out a fresh clone and runs the budget script directly; dist/ was wiped by `clean` but not rebuilt; an incorrect --dist argument points at an empty directory.","solutions":["Run the dashboard build command (BUILD_COMMANDS.dashboard, e.g. `npm run build:dashboard`) so dist/dashboard.html exists","Verify the distDir argument passed to the script points at the real Vite output directory","Check file permissions on dist/dashboard.html if the build output exists but is unreadable","Re-run a clean full build if dashboard.html exists but is stale/corrupt"],"exampleFix":"// before: checking budgets on a clean tree\nnode scripts/bundle-budgets.mjs --dist dist\n// after: build first, then check\nnpm run build:dashboard && node scripts/bundle-budgets.mjs --dist dist","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs';\nif (!existsSync(join(distDir, 'dashboard.html'))) throw new Error(`run the dashboard build before budget checks: ${distDir}/dashboard.html missing`);","typeGuard":"const dashboardBuilt = (distDir) => existsSync(join(distDir, 'dashboard.html'));","tryCatchPattern":"try {\n  measureBudgets(distDir);\n} catch (e) {\n  if (e.message.includes('cannot read') && e.message.includes('dashboard.html')) {\n    execSync('npm run build:dashboard', { stdio: 'inherit' });\n    measureBudgets(distDir);\n  } else throw e;\n}","preventionTips":["Always build the dashboard before running bundle budget checks","Chain budget checks after the build in CI (`build && check`)","Verify the distDir path passed to the script","Avoid cleaning dist/ without rebuilding"],"tags":["build","file-not-found","vite","ci"],"backgroundTag":"file-not-found","analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-09-15T16:44:39.439Z","contentChangedAt":"2026-09-15T16:44:39.439Z","schemaVersion":2},"datasetVersion":"2026-09-15T18:17:12.389Z"}