jackwener/OpenCLI · error · CommandExecutionError
gov-policy ${command} browser extraction failed: ${error?.me
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.
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)
Solutions
- Read the inner message to identify the root cause (timeout vs crash vs navigation)
- Ensure a supported headless browser is installed and launchable (check Puppeteer deps in CI)
- Retry the command — transient navigation/timeouts often succeed on a second attempt
- 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
- Ensure Chromium/Puppeteer and its system libraries are installed, especially in CI containers
- Set generous navigation timeouts for slow government sites
- Retry transient navigation failures once before surfacing errors
- Distinguish known CLI error types from foreign errors to keep messages actionable
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
- FRAMEWORK_CHANGED
- gov-policy search
- gov-policy ${command} page did not expose readable result ro
- gov-policy ${command} extractor returned no result rows
- Browser session required for instagram story
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/cd90ddeee751b64a.
Report an issue: GitHub.