{"record":{"id":"66fc9eedf050cdf1","repo":"jackwener/OpenCLI","slug":"browser-page-required-66fc9e","errorCode":null,"errorMessage":"Browser page required","messagePattern":"Browser page required","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/v2ex/daily.js","lineNumber":18,"sourceCode":"/**\n * V2EX Daily Check-in adapter.\n */\nimport { CommandExecutionError } from '@jackwener/opencli/errors';\nimport { cli, Strategy } from '@jackwener/opencli/registry';\ncli({\n    site: 'v2ex',\n    name: 'daily',\n    access: 'write',\n    description: 'V2EX 每日签到并领取铜币',\n    domain: 'www.v2ex.com',\n    strategy: Strategy.COOKIE,\n    browser: true,\n    args: [],\n    columns: ['status', 'message'],\n    func: async (page) => {\n        if (!page)\n            throw new CommandExecutionError('Browser page required');\n        if (process.env.OPENCLI_VERBOSE) {\n            console.error('[opencli:v2ex] Navigating to /mission/daily');\n        }\n        await page.goto('https://www.v2ex.com/mission/daily');\n        // Cloudflare challenge bypass wait\n        for (let i = 0; i < 5; i++) {\n            await new Promise(r => setTimeout(r, 1500));\n            const title = await page.evaluate(`() => document.title`);\n            if (!title?.includes('Just a moment'))\n                break;\n            if (process.env.OPENCLI_VERBOSE)\n                console.error('[opencli:v2ex] Waiting for Cloudflare...');\n        }\n        // Evaluate DOM to find if we need to check in\n        const checkResult = await page.evaluate(`\n      async () => {\n        const btn = document.querySelector('input.super.normal.button');\n        if (!btn || !btn.value.includes('领取')) {","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/v2ex/daily.js#L1-L36","documentation":"The v2ex daily command runs with Strategy.COOKIE and browser:true, so the registry should hand the command a live browser page. The command throws CommandExecutionError('Browser page required') when func receives a falsy page, meaning the browser layer failed to launch or attach a page before the command body ran. It guards against dereferencing page.goto on null.","triggerScenarios":"Calling the v2ex daily command when the underlying browser/page object is null or undefined — e.g. browser launch failed upstream, headless environment lacks a browser binary, or the command was invoked through a path that skips browser provisioning.","commonSituations":"Playwright/Chromium not installed in the environment; running in CI or a container with no browser and missing deps; corrupted browser profile; a registry change or wrapper invoking func without a page.","solutions":["Install/repair the browser runtime the opencli browser strategy depends on (e.g. playwright install chromium) and its system dependencies.","Re-run the command normally through the CLI so the registry provisions the browser page, rather than calling func directly with no page.","Check earlier logs for a browser-launch failure (profile lock, missing binary) and fix the root cause.","Verify no other process is holding a lock on the browser user-data-dir."],"exampleFix":"// before: invoking the command function directly\nawait dailyFunc(null);\n// after: run through the CLI/registry so a page is provisioned\n// $ opencli v2ex daily","handlingStrategy":"validation","validationCode":"if (!page || typeof page.goto !== 'function') {\n  throw new Error('Browser page unavailable — install the browser runtime (e.g. playwright install chromium) and run via the CLI');\n}","typeGuard":"function hasPage(p) {\n  return !!p && typeof p === 'object' && typeof p.goto === 'function' && typeof p.evaluate === 'function';\n}","tryCatchPattern":"try {\n  await runDailyCommand();\n} catch (e) {\n  if (e.message === 'Browser page required') {\n    // fix environment: install browser binary/deps, then retry\n  } else throw e;\n}","preventionTips":["Install the browser runtime and system dependencies before running browser-strategy commands.","Invoke commands through the CLI/registry so a page is provisioned, never call func directly with null.","Check for browser profile/user-data-dir locks in CI before launching.","Smoke-test browser launch (open about:blank) in fresh environments."],"tags":["browser","environment","null-check"],"backgroundTag":"browser-page-not-available","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}