jackwener/OpenCLI · error · CommandExecutionError

Browser page required

Error message

Browser page required

What it means

The v2ex notifications command (browser:true, Strategy.COOKIE) throws CommandExecutionError('Browser page required') when func receives a falsy page. Like the other v2ex browser commands, it guards against calling page.goto on null when the browser layer failed to provision a page.

Source

Thrown at clis/v2ex/notifications.js:20

 * V2EX Notifications adapter.
 */
import { CommandExecutionError } from '@jackwener/opencli/errors';
import { cli, Strategy } from '@jackwener/opencli/registry';
cli({
    site: 'v2ex',
    name: 'notifications',
    access: 'read',
    description: 'V2EX 获取提醒 (回复/由于)',
    domain: 'www.v2ex.com',
    strategy: Strategy.COOKIE,
    browser: true,
    args: [
        { name: 'limit', type: 'int', default: 20, help: 'Number of notifications' }
    ],
    columns: ['type', 'content', 'time'],
    func: async (page, kwargs) => {
        if (!page)
            throw new CommandExecutionError('Browser page required');
        if (process.env.OPENCLI_VERBOSE) {
            console.error('[opencli:v2ex] Navigating to /notifications');
        }
        await page.goto('https://www.v2ex.com/notifications');
        await new Promise(r => setTimeout(r, 1500)); // waitForLoadState doesn't always work robustly
        // Evaluate DOM to extract notifications
        const data = await page.evaluate(`
      async () => {
        const items = Array.from(document.querySelectorAll('#Main .box .cell[id^="n_"]'));
        return items.map(item => {
          let type = '通知';
          let time = '';
          
          // determine type based on text content
          const text = item.textContent || '';
          if (text.includes('回复了你')) type = '回复';
          else if (text.includes('感谢了你')) type = '感谢';
          else if (text.includes('收藏了你')) type = '收藏';

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Install or repair the browser runtime (e.g. playwright install chromium) plus system dependencies.
  2. Run the command through the opencli CLI so a page is provisioned automatically.
  3. Inspect earlier logs for the actual browser-launch failure (missing binary, profile lock) and fix it.
  4. In programmatic use, pass a valid live page object to func rather than null/undefined.

Example fix

// before
await notificationsFunc(null, { limit: 20 });
// after: invoke via CLI/registry
// $ opencli v2ex notifications --limit 20
Defensive patterns

Strategy: validation

Validate before calling

if (!page || typeof page.goto !== 'function') {
  throw new Error('Browser page unavailable — install browser runtime and run through the CLI');
}

Type guard

function hasPage(p) {
  return !!p && typeof p === 'object' && typeof p.goto === 'function' && typeof p.evaluate === 'function';
}

Try / catch

try {
  await runNotifications({ limit: 20 });
} catch (e) {
  if (e.message === 'Browser page required') {
    // fix browser provisioning, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the v2ex notifications command when no browser page was supplied — browser launch failure, missing browser binary, or direct invocation of func without a page.

Common situations: Chromium/playwright not installed in a headless CI environment; browser user-data-dir locked; registry bypassed by calling the command function directly in tests or scripts.

Related errors


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