{"record":{"id":"8475fc9c8cbd26bd","repo":"santifer/career-ops","slug":"liveness-requires-playwright-with-chromium-run","errorCode":null,"errorMessage":"--liveness requires Playwright with Chromium (run \"npx playwright install chromium\"): ${err.message}","messagePattern":"--liveness requires Playwright with Chromium \\(run \"npx playwright install chromium\"\\): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scan-ats-full.mjs","lineNumber":560,"sourceCode":"        // Lowest not-yet-finished index: everything below it is complete, so\n        // a resumed run can restart exactly here without skipping work.\n        const resumeAt = inFlight.size ? Math.min(...inFlight) : next;\n        if (onItemDone) onItemDone({ done, resumeAt });\n      }\n    }\n  }\n  await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()));\n}\n\n// ── Liveness verification (reuses liveness-browser.mjs) ────────────\n\nasync function filterLive(offers) {\n  let chromium, checkUrlLiveness, newLivenessPage;\n  try {\n    ({ chromium } = await import('playwright'));\n    ({ checkUrlLiveness, newLivenessPage } = await import('./liveness-browser.mjs'));\n  } catch (err) {\n    throw new Error(\n      `--liveness requires Playwright with Chromium (run \"npx playwright install chromium\"): ${err.message}`,\n      { cause: err },\n    );\n  }\n  console.error(`\\nVerifying liveness of ${offers.length} match(es) with Playwright (sequential)...`);\n  const browser = await chromium.launch({ headless: true });\n  const live = [];\n  try {\n    const page = await newLivenessPage(browser);\n    // Sequential — project rule: never Playwright in parallel\n    for (const offer of offers) {\n      const { result, reason } = await checkUrlLiveness(page, offer.url);\n      const icon = result === 'active' ? '✅' : result === 'expired' ? '❌' : '⚠️';\n      console.error(`  ${icon} ${result.padEnd(9)} ${offer.company} | ${offer.title}${result === 'expired' ? ` (${reason})` : ''}`);\n      if (result !== 'expired') live.push(offer); // keep 'uncertain' — transient errors retry next scan\n    }\n  } finally {\n    await browser.close();","sourceCodeStart":542,"sourceCodeEnd":578,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/scan-ats-full.mjs#L542-L578","documentation":"filterLive() in scan-ats-full.mjs dynamically imports 'playwright' and './liveness-browser.mjs' to verify posting liveness via a headless browser. If the import fails (playwright package not installed or not resolvable), it throws an Error with a cause chain pointing to the underlying module error, and a remediation hint to install Chromium.","triggerScenarios":"Running `scan-ats-full.mjs --liveness` in an environment where the playwright npm package is not installed, not in node_modules, or the module resolution fails. The import('playwright') promise rejects.","commonSituations":"Fresh checkout without running npm install; a trimmed/Docker environment that excluded playwright to save space; a monorepo where playwright is a peer/optional dependency not hoisted; Node version incompatibility with the installed playwright.","solutions":["Install playwright: npm install playwright (or npm install -D playwright).","Install the Chromium browser binary: npx playwright install chromium.","If you do not need liveness checks, re-run without the --liveness flag.","Verify the import resolves: node -e \"import('playwright').then(() => console.log('ok'))\"."],"exampleFix":"# before: --liveness used without playwright installed\nnode scan-ats-full.mjs --liveness\n\n# after: install then run\nnpm install playwright && npx playwright install chromium\nnode scan-ats-full.mjs --liveness","handlingStrategy":"validation","validationCode":"async function canImportPlaywright() {\n  try { await import('playwright'); return true; }\n  catch { return false; }\n}\nif (opts.liveness && !(await canImportPlaywright())) {\n  throw new Error('Install playwright to use --liveness: npm install playwright && npx playwright install chromium');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await runScanWithLiveness();\n} catch (err) {\n  if (err.message.includes('requires Playwright')) {\n    console.error(err.message);\n    console.error('Falling back to non-liveness scan — re-run without --liveness.');\n    opts.liveness = false;\n    await runScanWithoutLiveness();\n  } else throw err;\n}","preventionTips":["Check playwright availability before offering the --liveness flag in your CLI wrapper.","Document playwright + chromium install as a prerequisite in onboarding for liveness features.","In CI, run `npx playwright install chromium` as a setup step."],"tags":["playwright","liveness","dynamic-import","dependencies","scan"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}