{"record":{"id":"766d58d19976cff7","repo":"jackwener/OpenCLI","slug":"gov-policy-command-page-did-not-expose-readable","errorCode":null,"errorMessage":"gov-policy ${command} page did not expose readable result rows","messagePattern":"gov-policy (.+?) page did not expose readable result rows","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/gov-policy/utils.js","lineNumber":33,"sourceCode":"    if (!Number.isInteger(limit) || limit < 1) {\n        throw new ArgumentError(`gov-policy ${command} --limit must be a positive integer`);\n    }\n    if (limit > 20) {\n        throw new ArgumentError(`gov-policy ${command} --limit must be <= 20`);\n    }\n    return limit;\n}\n\nexport function classifyExtractorFailure(command, result) {\n    const sample = String(result?.sample || '').replace(/\\s+/g, ' ').trim();\n    const url = String(result?.url || '').trim();\n    if (command === 'search' && EMPTY_RESULT_PATTERNS.some((pattern) => pattern.test(sample))) {\n        throw new EmptyResultError('gov-policy search', sample ? sample.slice(0, 160) : undefined);\n    }\n    const context = [url && `url=${url}`, sample && `sample=${sample.slice(0, 160)}`]\n        .filter(Boolean)\n        .join('; ');\n    throw new CommandExecutionError(\n        `gov-policy ${command} page did not expose readable result rows`,\n        context || 'The page structure may have changed or the page did not finish rendering.',\n    );\n}\n\nexport function requireRows(command, rows) {\n    if (!Array.isArray(rows) || rows.length === 0) {\n        throw new CommandExecutionError(\n            `gov-policy ${command} extractor returned no result rows`,\n            'The page structure may have changed or all result cards were missing required title fields.',\n        );\n    }\n    return rows;\n}\n\nexport function wrapBrowserError(command, error) {\n    if (error instanceof ArgumentError || error instanceof EmptyResultError || error instanceof CommandExecutionError) {\n        throw error;","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gov-policy/utils.js#L15-L51","documentation":"Thrown by classifyExtractorFailure as the fallback when the extractor ran but the page contained no readable result rows and (for search) no empty-result pattern matched. This means the command could not tell whether there were results — the page DOM didn't match the selectors, or it never finished rendering. Wrapped as CommandExecutionError with any url/sample context captured.","triggerScenarios":"Calling any gov-policy subcommand where result.sample lacks the expected result-card structure and no EMPTY_RESULT_PATTERNS phrase is present: selector mismatch after a site redesign, JS-rendered content not yet loaded at extraction time, or a bot-check/interstitial page served instead of results.","commonSituations":"gov-policy site layout change, very slow network so content hasn't rendered when the extractor samples the DOM, anti-bot challenge pages, wrong command targeting a page type the extractor doesn't know.","solutions":["Re-run the command — transient rendering/timing issues often resolve","Increase patience for page load if the CLI exposes a wait/timeout option, or retry on a faster connection","Check the captured url/sample in the error context in a browser to see what the page actually shows","Report a possible site structure change to the adapter maintainers with the context string"],"exampleFix":"// before\nawait runGovPolicy('search', { q: 'data security' });\n// after\ntry { await runGovPolicy('search', { q: '数据安全' }); }\ncatch (e) { await sleep(3000); await runGovPolicy('search', { q: '数据安全' }); } // retry once for render lag","handlingStrategy":"retry","validationCode":"// Preflight: confirm the page renders result rows\nawait page.goto(url, { waitUntil: 'networkidle2' });\nconst hasRows = await page.evaluate(() => document.querySelectorAll('.result-item, .list-item').length > 0);\nif (!hasRows) console.warn('No result rows rendered; extraction may fail');","typeGuard":"function isReadableExtractorResult(r) { return r && typeof r.sample === 'string' && r.sample.trim().length > 0; }","tryCatchPattern":"try {\n  const rows = await govPolicyExtract(command, args);\n} catch (err) {\n  if (/did not expose readable result rows/.test(err.message)) {\n    await sleep(3000); // allow JS rendering\n    return govPolicyExtract(command, args); // retry once\n  }\n  throw err;\n}","preventionTips":["Retry once after a delay to accommodate slow JS rendering","Inspect the url/sample context in the error to diagnose page changes","Keep adapter selectors updated against site redesigns","Report recurring failures with the captured context to maintainers"],"tags":["web-scraping","extraction","gov-policy","dom"],"backgroundTag":"page-structure-changed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}