{"record":{"id":"bd53cf7c4b408e9e","repo":"DIYgod/RSSHub","slug":"bad-category-see-a-href-https-docs-rsshub-app-bd53cf","errorCode":null,"errorMessage":"Bad category. See <a href=\"https://docs.rsshub.app/routes/new-media#wang-yi-xin-wen-pai-hang-bang\">docs</a>","messagePattern":"Bad category\\. See <a href=\"https://docs\\.rsshub\\.app/routes/new-media#wang-yi-xin-wen-pai-hang-bang\">docs</a>","errorType":"validation","errorClass":"InvalidParameterError","httpStatus":503,"severity":"warning","filePath":"lib/routes/163/news/rank.ts","lineNumber":124,"sourceCode":"\n而所有分类（包括全站）的 **跟贴榜** 的统计时间皆仅包含 “24 小时”、“本周”、“本月”。即可用的\\`time\\`参数为\\`day\\`、\\`week\\`、\\`month\\`。\n:::\n\n新闻分类：\n\n| 全站  | 新闻 | 娱乐          | 体育   | 财经  | 科技 | 汽车 | 女人 | 房产  | 游戏 | 旅游   | 教育 |\n| ----- | ---- | ------------- | ------ | ----- | ---- | ---- | ---- | ----- | ---- | ------ | ---- |\n| whole | news | entertainment | sports | money | tech | auto | lady | house | game | travel | edu  |`,\n};\n\nasync function handler(ctx) {\n    const category = ctx.req.param('category') || 'whole';\n    const type = ctx.req.param('type') || 'click';\n    const time = ctx.req.param('time') || 'day';\n\n    const cfg = config[category];\n    if (!cfg) {\n        throw new InvalidParameterError('Bad category. See <a href=\"https://docs.rsshub.app/routes/new-media#wang-yi-xin-wen-pai-hang-bang\">docs</a>');\n    }\n    if ((category !== 'whole' && type === 'click' && time === 'month') || (category === 'whole' && type === 'click' && time === 'hour') || (type === 'follow' && time === 'hour')) {\n        throw new InvalidParameterError('Bad timeRange range. See <a href=\"https://docs.rsshub.app/routes/new-media#wang-yi-xin-wen-pai-hang-bang\">docs</a>');\n    }\n\n    const currentUrl = category === 'money' ? cfg.link : `${rootUrl}${cfg.link}`;\n    const response = await got({\n        method: 'get',\n        url: currentUrl,\n        responseType: 'buffer',\n    });\n\n    const $ = load(iconv.decode(response.data, 'gbk'));\n\n    const list = $('div.tabContents')\n        .eq(timeRange[time].index + (category === 'whole' ? (type === 'click' ? -1 : 2) : type === 'click' ? 0 : 2))\n        .find('table tbody tr td a')\n        .toArray()","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/163/news/rank.ts#L106-L142","documentation":"Thrown by the active (non-deprecated) NetEase 163 news rank route when :category is not a config key. Valid categories: whole, news, entertainment, sports, money, tech, auto, lady, house, game, travel, edu. Unlike the deprecated routes, this throws InvalidParameterError (an HTTP-400-mapping error type) and additionally validates the (category,type,time) combination for allowed time ranges.","triggerScenarios":"Request to /163/news/rank/<category>/... with a category not in config, OR an unsupported (category,type,time) triplet such as (money,click,hour) for whole or (*,click,month) for non-whole, or (any,follow,hour). The first throw is the 'Bad category' one.","commonSituations":"Category slug typo; using a Chinese label instead of its english key; or requesting a time range the docs tip explicitly disallows (e.g. whole + click + hour). Because type/time have their own valid sets (click|follow; hour|day|week|month) invalid values there fall through and surface as downstream index errors rather than this message.","solutions":["Use one of the eleven documented category keys (whole, news, entertainment, sports, money, tech, auto, lady, house, game, travel, edu).","Respect the time-range matrix in the route description: whole+click supports day/week/month; non-whole+click supports hour/day/week; follow supports day/week/month.","Set sensible defaults by omitting optional params (category defaults to whole, type to click, time to day)."],"exampleFix":"// before\nGET /163/news/rank/quan/click/day   // 'quan' not a key\n// after\nGET /163/news/rank/whole/click/day    // 全站, valid triplet","handlingStrategy":"validation","validationCode":"const CATEGORIES = ['whole','news','entertainment','sports','money','tech','auto','lady','house','game','travel','edu'];\nconst category = ctx.req.param('category') || 'whole';\nif (!CATEGORIES.includes(category)) throw new Error(`Bad category '${category}'. Valid: ${CATEGORIES.join(', ')}`);\n// also enforce the (category,type,time) matrix from the route description\nconst type = ctx.req.param('type') || 'click';\nconst time = ctx.req.param('time') || 'day';\nconst bad = (category !== 'whole' && type === 'click' && time === 'month')\n  || (category === 'whole' && type === 'click' && time === 'hour')\n  || (type === 'follow' && time === 'hour');\nif (bad) throw new Error('Unsupported (category,type,time) combination');","typeGuard":"type Category = 'whole'|'news'|'entertainment'|'sports'|'money'|'tech'|'auto'|'lady'|'house'|'game'|'travel'|'edu';\nconst isCategory = (v: string): v is Category =>\n  ['whole','news','entertainment','sports','money','tech','auto','lady','house','game','travel','edu'].includes(v as Category);","tryCatchPattern":"import { InvalidParameterError } from '@/errors/types/invalid-parameter';\ntry { await handler(ctx); }\ncatch (e) {\n  if (e instanceof InvalidParameterError) return respond400(e.message); // user error\n  throw e;\n}","preventionTips":["Catch InvalidParameterError specifically — it maps to HTTP 400, unlike plain Errors.","Validate the full triplet, not just category, since some combinations are semantically invalid."],"tags":["rsshub","parameter-validation","active-route","new-media","typescript","invalid-parameter-error"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}