{"record":{"id":"9bbc0bc5932035aa","repo":"DIYgod/RSSHub","slug":"error-fetching-announcements-error","errorCode":null,"errorMessage":"Error fetching announcements: ${error}","messagePattern":"Error fetching announcements: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/xbmu/announcement.ts","lineNumber":73,"sourceCode":"                            description: content,\n                            category: ['university'],\n                            guid: item.link,\n                            id: item.link,\n                            image: 'http://210.26.0.114:9090/mdxg/img/weex/default_img.jpg',\n                            content,\n                            updated: item.date,\n                            language: 'zh-CN',\n                        };\n                    })\n                )\n            )) as DataItem[],\n            allowEmpty: true,\n            language: 'zh-CN',\n            feedLink: 'https://rsshub.app/xbmu/announcement',\n            id: 'https://rsshub.app/xbmu/announcement',\n        };\n    } catch (error) {\n        throw new Error(`Error fetching announcements: ${error}`, { cause: error });\n    }\n};\n\nexport const route: Route = {\n    path: '/announcement',\n    name: '通知公告',\n    maintainers: ['PrinOrange'],\n    handler,\n    categories: ['university'],\n    features: {\n        requireConfig: false,\n        requirePuppeteer: false,\n        antiCrawler: false,\n        supportBT: false,\n        supportPodcast: false,\n        supportScihub: false,\n    },\n    example: '/xbmu/announcement',","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/xbmu/announcement.ts#L55-L91","documentation":"Catch-all wrapping the entire /xbmu/announcement handler; identical pattern to the academic route. Any exception during list/detail fetch or parse is re-thrown with an 'Error fetching announcements:' prefix and { cause: error }.","triggerScenarios":"got(BASE_URL) (tzgg.htm) or got(item.link) fails, or load()/cheerio throws on bad HTML, caught at announcement.ts:72-74.","commonSituations":"Announcement page (tzgg.htm) unreachable, returning a redirect/error page, or markup changed so ITEM_SELECTOR matches nothing (which itself does not throw but indicates staleness).","solutions":["Read error.cause to find the underlying HTTP/parse error.","Confirm https://www.xbmu.edu.cn/xwzx/tzgg.htm is reachable and returns the expected HTML.","If selectors drifted, update announcement.ts:17 and report upstream."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"try {\n    const r = await got.head('https://www.xbmu.edu.cn/xwzx/tzgg.htm', { timeout: 5000 });\n    if (r.statusCode >= 400) throw new Error(`xbmu returned ${r.statusCode}`);\n} catch {\n    throw new Error('xbmu announcement source unreachable');\n}","typeGuard":"function isXbmuAnnouncementError(e: unknown): boolean {\n    return e instanceof Error && /Error fetching announcements/i.test(e.message);\n}","tryCatchPattern":"try {\n    return await xbmuAnnouncementHandler();\n} catch (e) {\n    const root = isXbmuAnnouncementError(e) ? (e.cause ?? e) : e;\n    if (root instanceof Error && /ENOTFOUND|ETIMEDOUT/i.test(root.message)) {\n        await scheduleRetry();\n    }\n    throw e;\n}","preventionTips":["Read error.cause to locate the failing step (list vs detail vs parse).","Fail fast on non-HTML responses (login redirects) instead of letting cheerio parse them.","Report selector drift to the maintainer promptly; campus sites change templates often."],"tags":["xbmu","network","error-wrapping","scraping","university"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}