{"record":{"id":"abfcbc80b88501a5","repo":"jackwener/OpenCLI","slug":"aibase-news","errorCode":null,"errorMessage":"aibase news","messagePattern":"aibase news","errorType":"validation","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/aibase/news.js","lineNumber":77,"sourceCode":"    if (!payload || typeof payload !== 'object') {\n        throw new CommandExecutionError('AIbase daily page returned an unreadable payload');\n    }\n    if (!payload.ok) {\n        const reason = typeof payload.reason === 'string' && payload.reason.trim() ? payload.reason.trim() : 'selector-drift';\n        throw new CommandExecutionError(\n            `AIbase daily selector drift: ${reason}`,\n            payload.title ? `Page title: ${payload.title}` : undefined,\n        );\n    }\n    const rows = (Array.isArray(payload.rows) ? payload.rows : [])\n        .map((row, index) => ({\n            rank: index + 1,\n            title: normalizeText(row.title),\n            url: normalizeText(row.url),\n        }))\n        .filter((row) => row.title && row.url);\n    if (rows.length === 0) {\n        throw new EmptyResultError('aibase news', 'AIbase daily page loaded, but no article rows with title and URL were extracted.');\n    }\n    return rows.slice(0, limit).map((row, index) => ({ ...row, rank: index + 1 }));\n}\n\nasync function loadAibaseNews(page, args) {\n    const limit = normalizeLimit(args.limit);\n    await page.goto(AIBASE_DAILY_URL, { waitUntil: 'load', settleMs: 3000 });\n    const payload = await page.evaluate(buildExtractAibaseNewsJs()).catch((error) => {\n        throw new CommandExecutionError(`Failed to extract AIbase daily news: ${getErrorMessage(error)}`);\n    });\n    return toRows(payload, limit);\n}\n\nexport const aibaseNewsCommand = cli({\n    site: 'aibase',\n    name: 'news',\n    access: 'read',\n    description: 'AIbase 日报 - 每天三分钟关注AI行业趋势',","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/aibase/news.js#L59-L95","documentation":"toRows throws an EmptyResultError labeled 'aibase news' when the AIbase daily page loaded and payload.ok was true, but after normalizing and filtering, no rows had both a title and a URL. The page rendered, extraction technically succeeded, yet zero usable articles were extracted.","triggerScenarios":"payload.rows exists but every row lacks title or url (empty anchor text, javascript:void(0) or empty hrefs), or payload.rows is missing/not an array so the fallback [] yields length 0.","commonSituations":"Site renders link cards as images without text (so innerText is empty); daily edition published with placeholder links; href attributes changed to relative routes filtered out by the script; A/B variant that doesn't set the classes the row extraction expects.","solutions":["Retry later — the daily page may be mid-update with placeholder content.","Inspect the live page's anchors (text and href) and update the extraction script's selector/row mapping so title and url are captured.","Check whether the site changed href formats (e.g. new route prefix) and adjust the script's filters.","Run the whoami/login command if the variant requiring authentication shows real content while the anonymous variant shows placeholders."],"exampleFix":"null","handlingStrategy":"fallback","validationCode":"null","typeGuard":"function hasRowWithTitleAndUrl(row) {\n  return !!row && typeof row.title === 'string' && row.title.trim() !== '' && typeof row.url === 'string' && row.url.trim() !== ''; \n}","tryCatchPattern":"try {\n  const rows = await fetchAibaseNews();\n} catch (e) {\n  if (e instanceof EmptyResultError && e.operation === 'aibase news') {\n    console.warn('No usable articles extracted; try again later or update extraction');\n  } else throw e;\n}","preventionTips":["Treat empty extractions as possibly transient (page mid-update) and retry","Filter expected placeholder links (no text, javascript: hrefs) proactively","Adjust selectors when the site shifts article markup into image-only cards","Handle EmptyResultError separately from hard failures in pipelines"],"tags":["browser-scraping","empty-results","cli"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}