{"record":{"id":"393b3c8a14cf84c7","repo":"pbakaus/impeccable","slug":"browser-script-not-found-at-browserscriptpath","errorCode":null,"errorMessage":"Browser script not found at ${browserScriptPath}","messagePattern":"Browser script not found at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/engine/engines/browser/detect-url.mjs","lineNumber":201,"sourceCode":"  }\n\n  // Read the browser detection script — reuse it instead of reimplementing\n  const browserScriptPath = path.resolve(\n    path.dirname(fileURLToPath(import.meta.url)),\n    '..',\n    '..',\n    'detect-antipatterns-browser.js'\n  );\n  let browserScript;\n  try {\n    browserScript = profileStep(profile, {\n      engine: 'browser',\n      phase: 'setup',\n      ruleId: 'read-browser-script',\n      target: url,\n    }, () => fs.readFileSync(browserScriptPath, 'utf-8'));\n  } catch {\n    throw new Error(`Browser script not found at ${browserScriptPath}`);\n  }\n\n  // CI runners (GitHub Actions Ubuntu) block unprivileged user namespaces, so\n  // Chrome can't initialize its sandbox there. Disable the sandbox only when\n  // running in CI; local users keep the default hardened launch.\n  const launchArgs = process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox'] : [];\n  const browser = externalBrowser || await profileStepAsync(profile, {\n    engine: 'browser',\n    phase: 'load',\n    ruleId: 'launch-browser',\n    target: url,\n  }, () => launchBrowser(puppeteer, { headless: options?.headless ?? true, args: launchArgs }));\n  const page = await profileStepAsync(profile, {\n    engine: 'browser',\n    phase: 'load',\n    ruleId: 'new-page',\n    target: url,\n  }, () => browser.newPage());","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/pbakaus/impeccable/blob/d14711ae3d1a1dd62dee61a358d27f107c51ccd0/cli/engine/engines/browser/detect-url.mjs#L183-L219","documentation":"Thrown when the browser-engine URL detector cannot read the compiled detector script detect-antipatterns-browser.js, which it injects into the page via puppeteer's evaluateOnNewDocument. That file is a build artifact regenerated by `bun run build:browser`; it is not hand-authored. The path is resolved relative to the engine source so it must sit two directories up from detect-url.mjs.","triggerScenarios":"Running the URL detector from source (cli/engine/engines/browser/detect-url.mjs) before the browser bundle has been built, so detect-antipatterns-browser.js does not exist at ../detect-antipatterns-browser.js. Also fires if the file was gitignored/deleted or the working directory layout was reorganized so the relative resolution misses.","commonSituations":"Fresh clone where `bun run build` was never run; running the CLI out of dist/ vs source mismatch; a refactor that moved the engine directory without updating the path.resolve('../..' + filename) hop; CI that installs the npm package but only ships source, not the prebuilt browser bundle.","solutions":["Run `bun run build:browser` (or the full `bun run build`) to regenerate cli/engine/detect-antipatterns-browser.js, then retry.","Confirm the file exists at the printed browserScriptPath and is non-empty; the resolved path is in the error message.","If you moved the engine files, update the path.resolve('..', '..', 'detect-antipatterns-browser.js') hop in detect-url.mjs to match the new depth.","For published packages, ensure the build step runs before publish so the browser bundle ships in the tarball."],"exampleFix":"// before — file missing, fs.readFileSync throws ENOENT, caught and re-thrown\n\n// after — regenerate the artifact before running the URL detector\n// $ bun run build:browser\n// then:\nconst results = await detectUrl('https://example.com');","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs';\nimport path from 'node:path';\nconst scriptPath = path.resolve(\n  path.dirname(fileURLToPath(import.meta.url)), '..', '..', 'detect-antipatterns-browser.js'\n);\nif (!existsSync(scriptPath)) {\n  throw new Error('Run `bun run build:browser` first to generate the detector script.');\n}","typeGuard":"function browserBundleReady(scriptPath) {\n  return existsSync(scriptPath) && statSync(scriptPath).size > 0;\n}","tryCatchPattern":"try {\n  await detectUrl(url, options);\n} catch (err) {\n  if (/Browser script not found/.test(err.message)) {\n    console.error('Detector bundle missing. Run `bun run build:browser` and retry.');\n  } else throw err;\n}","preventionTips":["Treat detect-antipatterns-browser.js as a build prerequisite; run `bun run build` in CI before URL scans.","Add a preflight existsSync check with a clearer remediation message.","Ship the prebuilt bundle in published packages so end users never hit this."],"tags":["build-artifact","browser-engine","missing-file","fs-read","build-step"],"backgroundTag":null,"analyzedSha":"d14711ae3d1a1dd62dee61a358d27f107c51ccd0","analyzedAt":"2026-08-13T00:52:25.771Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}