pbakaus/impeccable · error · Error

Chromium unavailable: ${err?.message || err}

Error message

Chromium unavailable: ${err?.message || err}

What it means

Thrown by the benchmark-detector browser run when puppeteer.launch fails to start a headless Chromium. The underlying launch error is appended so the caller can tell whether Chromium is missing, lacks permissions, or hit a sandbox issue.

Source

Thrown at scripts/benchmark-detector.mjs:399

      mode: 'pure-vs-overlay',
      target: serverInfo.baseUrl,
      run: async (profile) => {
        let browser;
        const launchStarted = nowMs();
        try {
          browser = await puppeteer.default.launch({
            headless: true,
            args: process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox'] : [],
          });
          addEvent(profile, {
            engine: 'browser',
            phase: 'load',
            ruleId: 'launch-browser-overlay-bench',
            target: serverInfo.baseUrl,
            ms: nowMs() - launchStarted,
          });
        } catch (err) {
          throw new Error(`Chromium unavailable: ${err?.message || err}`);
        }

        let findings = [];
        try {
          const page = await browser.newPage();
          const url = `${serverInfo.baseUrl}/fixtures/antipatterns/${browserFiles[0]}`;
          const browserScript = fs.readFileSync(path.join(ROOT, 'cli', 'engine', 'detect-antipatterns-browser.js'), 'utf-8');
          await page.setViewport({ width: 1280, height: 800 });
          await page.goto(url, { waitUntil: 'load', timeout: 30000 });
          await new Promise(resolve => setTimeout(resolve, 100));
          await page.evaluate(() => { window.__IMPECCABLE_CONFIG__ = { autoScan: false }; });
          await page.evaluate(browserScript);
          const pureStarted = nowMs();
          findings = await page.evaluate(() => {
            const serialized = window.impeccableDetect({ decorate: false, serialize: true });
            return serialized.flatMap(({ findings }) => findings.map(f => ({ id: f.type, snippet: f.detail })));
          });
          addEvent(profile, {

View on GitHub (pinned to d14711ae3d)

Solutions

  1. Install the browser cache: `npx puppeteer install chromium` (or `puppeteer browsers install chrome`).
  2. In CI, ensure the launch args include --no-sandbox (the script already does this when process.env.CI is set).
  3. Verify system dependencies for Chromium are present (libnss3, libatk, etc.) and the cache path is writable.

Example fix

# before: Chromium not installed
node scripts/benchmark-detector.mjs --engine browser

# after
npx puppeteer install chromium
node scripts/benchmark-detector.mjs --engine browser
Defensive patterns

Strategy: try-catch

Validate before calling

import { existsSync } from 'node:fs';
import puppeteer from 'puppeteer';
async function chromiumAvailable() {
  try {
    const b = await puppeteer.default.launch({ headless: true });
    await b.close();
    return true;
  } catch { return false; }
}

Type guard

async function canLaunchChromium() {
  try {
    const b = await puppeteer.default.launch({ headless: 'new' });
    await b.close();
    return true;
  } catch { return false; }
}

Try / catch

try {
  browser = await puppeteer.default.launch({ headless: true });
} catch (err) {
  console.warn(`Chromium unavailable: ${err.message}; skipping browser engine`);
  return; // skip the browser run instead of aborting the whole benchmark
}

Prevention

When it happens

Trigger: Running the browser-engine benchmark when Chromium is not installed, cannot run headless in the current environment, or fails to launch within puppeteer.

Common situations: Fresh CI without `npx puppeteer install chromium`, a sandbox that blocks Chrome launch, or a broken puppeteer cache.

Related errors


AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13). Data as JSON: /api/errors/98eb5d381d6f38ea. Report an issue: GitHub.