{"record":{"id":"bb45c3d8e95cf842","repo":"jackwener/OpenCLI","slug":"github-trending-parser-drift-missing-field-for","errorCode":null,"errorMessage":"github-trending parser drift: missing ${field} for ${repo}","messagePattern":"github-trending parser drift: missing (.+?) for (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/github-trending/repos.js","lineNumber":40,"sourceCode":"function stripTags(value) {\n    return String(value ?? '').replace(/<[^>]*>/g, '');\n}\n\nfunction parseCount(value) {\n    if (value == null) return null;\n    const digits = String(value).replace(/[,\\s]/g, '');\n    if (!/^\\d+$/.test(digits)) return null;\n    return Number(digits);\n}\n\nfunction escapeRegExp(value) {\n    return String(value).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction assertCount(value, field, repo) {\n    const count = parseCount(value);\n    if (count == null) {\n        throw new CommandExecutionError(`github-trending parser drift: missing ${field} for ${repo}`);\n    }\n    return count;\n}\n\nfunction hasExplicitEmptyTrending(html) {\n    return /don.t have any trending repositories/i.test(stripTags(html))\n        || /no trending repositories/i.test(stripTags(html));\n}\n\nfunction parseTrendingHtml(html, limit) {\n    const blocks = Array.from(String(html ?? '').matchAll(/<article\\b[^>]*class=\"[^\"]*\\bBox-row\\b[^\"]*\"[^>]*>([\\s\\S]*?)<\\/article>/g))\n        .map((match) => match[1]);\n    const rows = [];\n\n    if (blocks.length === 0) {\n        if (hasExplicitEmptyTrending(html)) return rows;\n        throw new CommandExecutionError('github-trending parser drift: no repository rows found');\n    }","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/github-trending/repos.js#L22-L58","documentation":"During HTML parsing of the GitHub Trending page, a repository row was matched but a required count field (stars, forks, or stars-since) could not be parsed, so assertCount throws this CommandExecutionError. The library treats an unparsable count as 'parser drift' — GitHub changed its markup and the scraper's regexes no longer align with the page structure.","triggerScenarios":"parseTrendingHtml processes a Box-row article block whose stars/forks/starsSince text does not match the parseCount format (e.g. GitHub changes '1,234 stars' markup to a different label, icon-only counts, or localized number formats).","commonSituations":"GitHub ships a redesign of the Trending page; scraping a localized-language page where 'stars'/'forks' labels differ; page served with new count formatting like 'k' abbreviations the parser doesn't handle.","solutions":["Update the CLI/scraper package to the latest version where the parser regexes may already be fixed","Retry later if GitHub is mid-deploy of a UI change; check whether the trending page renders normally in a browser","Patch parseCount/assertCount regexes locally to accommodate the new markup and file an issue upstream"],"exampleFix":"// before\nconst count = parseCount(value);\n// after: tolerate abbreviated counts\nconst count = parseCount(value) ?? parseAbbreviatedCount(value); // '1.2k' -> 1200","handlingStrategy":"fallback","validationCode":"null","typeGuard":"function isParserDrift(e) { return e instanceof Error && /parser drift/.test(e.message); }","tryCatchPattern":"try {\n  const repos = parseTrendingHtml(html);\n} catch (e) {\n  if (/parser drift/.test(e.message)) { reportParserDrift(e); return cachedOrEmptyResult(); }\n  throw e;\n}","preventionTips":["Pin/regularly update the scraper package so parser fixes arrive quickly","Snapshot GitHub trending HTML in tests to detect markup changes early","Monitor this error as a signal that GitHub changed its Trending page"],"tags":["scraping","parser-drift","github","html-parsing"],"backgroundTag":"parser-drift-html-structure-changed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}