{"record":{"id":"232e8ab56a61abd4","repo":"DIYgod/RSSHub","slug":"no-articles-found","errorCode":null,"errorMessage":"No articles found.","messagePattern":"No articles found\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/cline/blog.ts","lineNumber":57,"sourceCode":"                : null;\n        })\n        .filter(Boolean) as DataItem[];\n}\n\nasync function handler() {\n    // Use the archive page which has all articles\n    const archiveUrl = `${rootUrl}/blog/archive`;\n\n    const response = await got({\n        method: 'get',\n        url: archiveUrl,\n    });\n\n    const $ = load(response.data);\n    const articles = extractArticlesFromDOM($);\n\n    if (articles.length === 0) {\n        throw new Error('No articles found.');\n    }\n\n    return {\n        title: 'Cline Official Blog',\n        link: blogUrl,\n        item: articles,\n        description: 'Cline Official Blog - AI Coding Assistant',\n        language: 'en' as const,\n    };\n}\n\nexport const route: Route = {\n    path: '/blog',\n    categories: ['blog'],\n    example: '/cline/blog',\n    parameters: {},\n    features: {\n        requireConfig: false,","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/cline/blog.ts#L39-L75","documentation":"Thrown by the Cline blog route when `extractArticlesFromDOM($)` returns an empty array after loading `${rootUrl}/blog/archive`. This is a defensive guard against a silent empty feed — it signals that the DOM selectors no longer match Cline's archive markup. Plain `Error`.","triggerScenarios":"Cline ships a new blog layout and the archive card selectors change; the archive URL moves or returns a SPA shell with no server-rendered articles; a CDN/Cloudflare interstitial page replaces the real HTML.","commonSituations":"Site redesign, anti-bot challenge page, or the route's `extractArticlesFromDOM` selectors drifting from the live DOM.","solutions":["Open `https://cline.com/blog/archive` (or whatever rootUrl resolves to) and inspect the article card markup.","Update the selectors inside `extractArticlesFromDOM` to match the new class names / structure.","Check the HTTP status and body returned by `got` — if it is a challenge page, add headers (User-Agent via `config.trueUA`) or switch to Puppeteer."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"function hasArticlesExtracted(arr: unknown[]): boolean {\n    return arr.length > 0;\n}","tryCatchPattern":"let articles: unknown[] = [];\nfor (let attempt = 0; attempt < 2; attempt++) {\n    const resp = await got({ method: 'get', url: archiveUrl });\n    articles = extractArticlesFromDOM(load(resp.data));\n    if (articles.length) break;\n}\nif (!articles.length) throw new Error('No articles found.');","preventionTips":["Keep the archive selectors in `extractArticlesFromDOM` aligned with the live DOM — add a snapshot test against a saved HTML fixture.","Send `config.trueUA` so Cline serves real content instead of a bot challenge.","Watch for status 403/503 — that signals a block, not a layout change."],"tags":["site-restructure","dom-scraping","response-shape","selector-drift"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}