{"record":{"id":"38d3dc47e072ec04","repo":"pbakaus/impeccable","slug":"puppeteer-is-required-for-url-scanning-install-n-38d3dc","errorCode":null,"errorMessage":"puppeteer is required for URL scanning. Install: npm install puppeteer","messagePattern":"puppeteer is required for URL scanning\\. Install: npm install puppeteer","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs","lineNumber":181,"sourceCode":"// ---------------------------------------------------------------------------\n\nasync function detectUrl(url, options = {}) {\n  const profile = options?.profile;\n  const waitUntil = options?.waitUntil || 'networkidle0';\n  const settleMs = Number.isFinite(options?.settleMs) ? options.settleMs : 0;\n  const viewport = options?.viewport || { width: 1280, height: 800 };\n  const externalBrowser = options?.browser || null;\n  let puppeteer;\n  if (!externalBrowser) {\n    try {\n      puppeteer = await profileStepAsync(profile, {\n        engine: 'browser',\n        phase: 'setup',\n        ruleId: 'import-puppeteer',\n        target: url,\n      }, () => import('puppeteer'));\n    } catch {\n      throw new Error('puppeteer is required for URL scanning. Install: npm install puppeteer');\n    }\n  }\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'));","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/pbakaus/impeccable/blob/d14711ae3d1a1dd62dee61a358d27f107c51ccd0/plugin/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs#L163-L199","documentation":"The URL scanning engine dynamically imports puppeteer (`import('puppeteer')`) to launch a headless browser and run the in-page anti-pattern checks. The import is skipped only when the caller supplies `options.browser` (an already-launched browser instance); otherwise a failure to resolve the puppeteer module is rethrown as this actionable error. It is a dependency/environment error, not a logic error.","triggerScenarios":"Calling detectUrl(url) (or the higher-level audit path that reaches it) with no options.browser and with puppeteer not installed in the running project's node_modules. The dynamic import() rejects, the catch block converts it into the user-facing message.","commonSituations":"Fresh checkout where `npm install puppeteer` was never run; CI image that omits the optional browser dependency; a monorepo where puppeteer is hoisted to a parent node_modules and the detector runs from a workspace that cannot resolve it; running `/impeccable audit` against a live URL before installing browser deps.","solutions":["Install the dependency: `npm install puppeteer` (or `bun add puppeteer`) in the project the detector runs from.","Reuse an already-launched browser by passing options.browser so the import path is skipped entirely.","In CI, also ensure Chrome can launch (the code already adds --no-sandbox when process.env.CI is set)."],"exampleFix":"// before\nawait detectUrl('https://example.com'); // no puppeteer, no shared browser\n\n// after (option A — install)\n// npm install puppeteer\n\n// after (option B — share a browser)\nawait detectUrl('https://example.com', { browser: sharedBrowser });","handlingStrategy":"validation","validationCode":"async function canResolvePuppeteer() {\n  try { await import('puppeteer'); return true; }\n  catch { return false; }\n}\n\nif (!options.browser && !await canResolvePuppeteer()) {\n  throw new Error('puppeteer is not installed; run `npm install puppeteer`');\n}\nawait detectUrl(url, options);","typeGuard":null,"tryCatchPattern":"try {\n  await detectUrl(url, options);\n} catch (e) {\n  if (String(e.message).includes('puppeteer is required')) {\n    // surface the install hint or fall back to the static (non-browser) detector\n    console.error(e.message);\n  } else throw e;\n}","preventionTips":["Add puppeteer to the project's dependencies where URL scanning is supported.","In CI, install puppeteer and rely on the built-in --no-sandbox handling (process.env.CI).","When scanning many URLs, pass a single shared options.browser to skip repeated imports/launches."],"tags":["browser","puppeteer","dependency","network"],"backgroundTag":null,"analyzedSha":"d14711ae3d1a1dd62dee61a358d27f107c51ccd0","analyzedAt":"2026-08-13T00:52:25.771Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}