{"record":{"id":"597a3efd78dc0c7c","repo":"DIYgod/RSSHub","slug":"no-such-sub-type","errorCode":null,"errorMessage":"No such sub type.","messagePattern":"No such sub type\\.","errorType":"validation","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/whu/rsgis.ts","lineNumber":205,"sourceCode":"async function handlePostList(type: string, sub: string): Promise<DataItem[]> {\n    let urlList: Array<{ url: string; base: string }> = [];\n    const category = categoryMap[type];\n    if (sub === 'all') {\n        const subMap = category.sub;\n        urlList = Object.values<{ path: string }>(subMap).map((value) => {\n            const subtype = value;\n            return {\n                url: `${baseUrl}/${category.path}/${subtype.path}.htm`,\n                base: `${baseUrl}/${category.path}`,\n            };\n        });\n    } else if (Object.hasOwn(category.sub, sub)) {\n        urlList.push({\n            url: `${baseUrl}/${category.path}/${category.sub[sub].path}.htm`,\n            base: `${baseUrl}/${category.path}`,\n        });\n    } else {\n        throw new Error('No such sub type.');\n    }\n    const urlPosts = await Promise.all(\n        urlList.map(async (url) => {\n            const response = await ofetch(url.url);\n            const $ = load(response);\n            return $('div.neiinner > div.nav_right > div.right_inner > div.list > ul > li')\n                .toArray()\n                .map((item) => parseListLinkDateItem($(item), url.base));\n        })\n    );\n    const fullList = await Promise.all(urlPosts.flat().map(async (item) => await getDetail(item)));\n    return fullList;\n}\n\nexport const route: Route = {\n    path: '/rsgis/:type/:sub?',\n    categories: ['university'],\n    example: '/whu/rsgis/index',","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/whu/rsgis.ts#L187-L223","documentation":"In handlePostList, for types xyxw/kxyj/tzgg, the sub parameter must be either 'all' or a key of categoryMap[type].sub (e.g. xyyw, hzjl, mtjj, xgyw for xyxw). Anything else reaches the else branch.","triggerScenarios":"Requesting /whu/rsgis/xyxw/<invalid> where <invalid> is not 'all' and not present in categoryMap[xyxw].sub — e.g. /whu/rsgis/xyxw/foo or a sub key that belongs to a different type.","commonSituations":"Cross-type sub confusion (using a kxyj sub like xsbg under xyxw), typo, or stale docs.","solutions":["Use 'all' or one of the sub keys listed in the route description table for the chosen type.","Double-check the sub belongs to the same type (subs are type-scoped in categoryMap).","Omit sub entirely — it defaults to 'all'."],"exampleFix":"// before\n/whu/rsgis/xyxw/xsbg   // xsbg belongs to kxyj, not xyxw\n// after\n/whu/rsgis/kxyj/xsbg","handlingStrategy":"validation","validationCode":"const category = categoryMap[type];\nconst validSubs = new Set(['all', ...Object.keys(category.sub)]);\nif (!validSubs.has(sub)) {\n    throw new InvalidParameterError(`sub must be one of: ${[...validSubs].join(', ')} — got ${sub}`);\n}","typeGuard":"function isValidSub(type: string, sub: string): boolean {\n    return sub === 'all' || Object.hasOwn(categoryMap[type]?.sub ?? {}, sub);\n}","tryCatchPattern":"try {\n    itemList = await handlePostList(type, sub);\n} catch (e) {\n    if (e instanceof Error && e.message === 'No such sub type.') {\n        throw new InvalidParameterError(`Unknown sub '${sub}' for type '${type}'`);\n    }\n    throw e;\n}","preventionTips":["Validate sub against the type-scoped categoryMap before fetching.","Surface valid options in the error message so callers self-correct.","Default sub to 'all' at the handler boundary so undefined never reaches the check."],"tags":["whu","route-parameter","validation"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}