jackwener/OpenCLI · error · CommandExecutionError

gov-policy browser extraction failed

Error message

gov-policy ${command} browser extraction failed: ${error?.message ?? error}

What it means

Thrown by wrapBrowserError as a catch-all: any error thrown during browser automation that is not already an ArgumentError, EmptyResultError, or CommandExecutionError is re-wrapped as `gov-policy <command> browser extraction failed: <message>`. This normalizes low-level failures (Puppeteer timeouts, target closed, navigation aborted) into the library's standard error type while preserving known errors untouched.

Solutions

  1. Read the inner message to identify the root cause (timeout vs crash vs navigation)
  2. Ensure a supported headless browser is installed and launchable (check Puppeteer deps in CI)
  3. Retry the command — transient navigation/timeouts often succeed on a second attempt
  4. Increase any available timeout options or run on a faster/stabler network connection

Example fix

// before
await runGovPolicy('search', { q: '网络安全' });
// after
try { await runGovPolicy('search', { q: '网络安全' }); }
catch (e) {
  if (/timeout|Target closed/i.test(e.message)) return retry(() => runGovPolicy('search', { q: '网络安全' }), 2);
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Preflight browser launchability before running extraction
let browser;
try { browser = await puppeteer.launch({ headless: true }); await browser.close(); }
catch (e) { throw new Error('Headless browser unavailable: ' + e.message); }

Type guard

function isKnownCliError(e) { return e instanceof ArgumentError || e instanceof EmptyResultError || e instanceof CommandExecutionError; }

Try / catch

try {
  await runGovPolicy(command, args);
} catch (err) {
  if (/browser extraction failed/.test(err.message)) {
    const cause = err.message.replace(/.*failed: /, '');
    if (/timeout|Target closed|Navigation/i.test(cause)) return retryCommand(command, args);
    if (/browser|sandbox|libnss/i.test(cause)) console.error('Install Chromium deps: check puppeteer setup in this environment.');
    else throw err;
  } else throw err;
}

Prevention

When it happens

Trigger: Calling a gov-policy command when the underlying browser operation throws a foreign error: page.goto() timeout, browser crashed or target closed, navigation interrupted, PermissionError launching the headless browser, or a TypeError inside the injected script.

Common situations: Chromium not installed or blocked by sandboxing in CI containers, slow/blocked network causing navigation timeouts, the site closing connections, or memory pressure killing the browser tab.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/cd90ddeee751b64a. Report an issue: GitHub.

Appendix: source

Thrown at clis/gov-policy/utils.js:53

        context || 'The page structure may have changed or the page did not finish rendering.',
    );
}

export function requireRows(command, rows) {
    if (!Array.isArray(rows) || rows.length === 0) {
        throw new CommandExecutionError(
            `gov-policy ${command} extractor returned no result rows`,
            'The page structure may have changed or all result cards were missing required title fields.',
        );
    }
    return rows;
}

export function wrapBrowserError(command, error) {
    if (error instanceof ArgumentError || error instanceof EmptyResultError || error instanceof CommandExecutionError) {
        throw error;
    }
    throw new CommandExecutionError(`gov-policy ${command} browser extraction failed: ${error?.message ?? error}`);
}

View on GitHub (pinned to 49907e53dc)