{"record":{"id":"47e550ddb39f95ec","repo":"DIYgod/RSSHub","slug":"invalid-category","errorCode":null,"errorMessage":"Invalid category","messagePattern":"Invalid category","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"lib/routes/blizzard/news-cn.ts","lineNumber":117,"sourceCode":"function getList(category, $) {\n    return Object.hasOwn(parsers, category) ? parsers[category]($) : [];\n}\n\nasync function fetchDetail(item, category) {\n    return await cache.tryGet(item.link, async () => {\n        const response = await ofetch(item.link);\n        const $ = load(response);\n\n        const parseDetail = detailParsers[category];\n        item.description = parseDetail($);\n        return item;\n    });\n}\n\nasync function handler(ctx) {\n    const category = ctx.req.param('category') || 'ow';\n    if (!Object.hasOwn(categoryNames, category)) {\n        throw new Error('Invalid category');\n    }\n\n    const rootUrl = `https://${category}.blizzard.cn/news`;\n\n    const response = await ofetch(rootUrl);\n    const $ = load(response);\n\n    const list = getList(category, $);\n    if (!list.length) {\n        throw new Error('No news found');\n    }\n\n    const items = await Promise.all(list.map((item) => fetchDetail(item, category)));\n\n    return {\n        title: `${categoryNames[category]}新闻`,\n        link: rootUrl,\n        item: items,","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/blizzard/news-cn.ts#L99-L135","documentation":"Generic Error validating the category path parameter of /blizzard/news-cn/:category? against the categoryNames map (ow, hs, wow). It prevents constructing a rootUrl from an unknown game subdomain and a downstream parser miss. The check uses Object.hasOwn for an exact-key lookup.","triggerScenarios":"A request with a category value that is not a key of categoryNames (e.g. 'overwatch', 'hots', 'd3', or a typo). The hasOwn check fails before any HTTP call.","commonSituations":"Using the full game name instead of the abbreviation; requesting a Blizzard game not covered (Heroes of the Storm, Diablo); URL typo.","solutions":["Use one of the supported abbreviations: ow (Overwatch), hs (Hearthstone), wow (World of Warcraft).","Omit the category to default to ow.","To add a game, extend categoryNames, parsers, and detailParsers and submit a PR."],"exampleFix":"// before\nif (!Object.hasOwn(categoryNames, category)) {\n    throw new Error('Invalid category');\n}\n// after (name the valid keys)\nif (!Object.hasOwn(categoryNames, category)) {\n    throw new Error(`Invalid category: ${category}. Valid: ${Object.keys(categoryNames).join(', ')}`);\n}","handlingStrategy":"validation","validationCode":"const category = ctx.req.param('category') || 'ow';\nif (!Object.hasOwn(categoryNames, category)) {\n    throw new Error(`Invalid category '${category}'. Valid: ${Object.keys(categoryNames).join(', ')}`);\n}","typeGuard":"type BlizzardCategory = keyof typeof categoryNames;\nconst isBlizzardCategory = (c: string): c is BlizzardCategory =>\n    Object.hasOwn(categoryNames, c);","tryCatchPattern":null,"preventionTips":["Document the three abbreviations (ow, hs, wow) in the route parameters.","When adding a game, extend categoryNames, parsers, and detailParsers atomically."],"tags":["blizzard","validation","path-parameter","enum"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}