{"record":{"id":"7aa91310340477dd","repo":"jackwener/OpenCLI","slug":"failed-to-read-hupu-hot-threads-message","errorCode":null,"errorMessage":"Failed to read hupu hot threads: ${message}","messagePattern":"Failed to read hupu hot threads: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/hupu/hot.js","lineNumber":132,"sourceCode":"  // hydrating; bbs.hupu.com is mostly SSR so this returns fast.\n  const start = Date.now();\n  while (document.querySelectorAll('.t-info').length === 0 && Date.now() - start < 5000) {\n    await new Promise(r => setTimeout(r, 100));\n  }\n  return extractHupuHotRowsFromDoc(document, ${JSON.stringify(limit)}, parseHupuCount);\n})()\n`;\n}\n\nasync function getHupuHot(page, args) {\n    const limit = normalizeHotLimit(args.limit);\n    await page.goto(`${HUPU_HOST}/`, { waitUntil: 'load', settleMs: 1000 });\n    let rows;\n    try {\n        rows = await page.evaluate(buildHotScript(limit));\n    } catch (error) {\n        const message = error instanceof Error ? error.message : String(error);\n        throw new CommandExecutionError(\n            `Failed to read hupu hot threads: ${message}`,\n            'bbs.hupu.com may be unreachable or its markup may have changed',\n        );\n    }\n    if (!Array.isArray(rows) || rows.length === 0) {\n        throw new EmptyResultError(\n            'hupu/hot',\n            'No threads found on bbs.hupu.com — page structure may have changed',\n        );\n    }\n    return rows;\n}\n\nexport const hotCommand = cli({\n    site: 'hupu',\n    name: 'hot',\n    access: 'read',\n    description: '虎扑首页热门帖子（含 lights / replies / forum / is_hot 列）',","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/hupu/hot.js#L114-L150","documentation":"getHupuHot navigates to bbs.hupu.com and runs buildHotScript(limit) inside the page to extract hot thread rows. If that page.evaluate throws (page unreachable, script error, markup mismatch causing a runtime exception), the error is wrapped as CommandExecutionError with the hint that the site may be unreachable or its markup changed.","triggerScenarios":"page.goto to bbs.hupu.com succeeds but the injected buildHotScript evaluate throws — timeout, navigation interrupted, selectors/DOM assumptions in the script breaking, or the page serving an error/anti-bot page with no expected structure.","commonSituations":"No network access or DNS failure to bbs.hupu.com; Hupu redesigned the hot-list markup; anti-bot interstitial (captcha) replacing the homepage; transient 5xx from Hupu; slow load exceeding settle/wait budgets.","solutions":["Retry the command — transient network or 5xx issues often resolve","Open https://bbs.hupu.com/ in a browser to confirm reachability and that the hot list renders","Inspect the inner error message (wrapped in this error) to see what the in-page script choked on","If markup changed, update buildHotScript selectors in clis/hupu/hot.js"],"exampleFix":"// before\nconst rows = await getHupuHot(page, 50);\n// after\nlet rows;\ntry { rows = await getHupuHot(page, 50); }\ncatch (e) {\n  console.error(e.message); // includes inner cause + hint\n  rows = [];\n}","handlingStrategy":"retry","validationCode":"const reachable = await fetch('https://bbs.hupu.com/', { method: 'HEAD' }).then(r => r.ok).catch(() => false);\nif (!reachable) throw new Error('bbs.hupu.com unreachable — check network');","typeGuard":"function isHotRows(v) {\n  return Array.isArray(v) && v.length > 0 && v.every(r => r && typeof r === 'object');\n}","tryCatchPattern":"try {\n  rows = await getHupuHot(page, limit);\n} catch (e) {\n  if (/Failed to read hupu hot threads/.test(e.message)) {\n    await sleep(3000); rows = await getHupuHot(page, limit); // one retry\n  } else throw e;\n}","preventionTips":["Retry once with backoff before failing — many causes are transient","Monitor bbs.hupu.com reachability from your runtime environment","Re-check buildHotScript selectors after Hupu redesigns","Use a realistic user-agent/profile to reduce anti-bot interference"],"tags":["network","scraping","hupu","browser-automation"],"backgroundTag":"page-evaluate-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}