{"record":{"id":"d0a2cb55935d65b9","repo":"DIYgod/RSSHub","slug":"invalid-type-or-subtype","errorCode":null,"errorMessage":"Invalid type or subtype","messagePattern":"Invalid type or subtype","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/gmu/yjs.ts","lineNumber":93,"sourceCode":"        supportPodcast: false,\n        supportScihub: false,\n    },\n    name: '研究生院',\n    maintainers: ['FrankFahey'],\n    radar: [\n        {\n            source: ['yjs.gmu.cn/:type/:subtype.htm', 'yjs.gmu.cn/'],\n            target: '/yjs/:type/:subtype',\n        },\n    ],\n    handler,\n};\n\nexport async function handler(ctx: Context) {\n    const { type, subtype } = ctx.req.param();\n\n    if (!Object.hasOwn(sections, type) || !Object.hasOwn(sections[type], subtype)) {\n        throw new Error('Invalid type or subtype');\n    }\n\n    const { title, path } = sections[type][subtype];\n    const baseUrl = 'https://yjs.gmu.cn';\n    const link = baseUrl + path;\n\n    const response = await got(link);\n\n    const $ = load(response.data);\n\n    // 更新选择器以匹配研究生院网站的实际结构\n    const list = $('.n_listxx1 li');\n\n    if (list.length === 0) {\n        throw new Error('No content found. The page structure might have changed.');\n    }\n\n    const items = await Promise.all(","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/gmu/yjs.ts#L75-L111","documentation":"Thrown by the GMU (Guangzhou Medical University) graduate school route when either the ':type' or ':subtype' path parameter does not match the nested 'sections' object structure. The sections object has five top-level keys (zsgz, pygz, xwgz, xsgz, xzzx), each containing valid subtype keys (e.g., tzgg, xwsd, gzzd). The check uses Object.hasOwn for both levels.","triggerScenarios":"A request to /gmu/yjs/:type/:subtype where type is not a key in sections, or where type exists but subtype is not a key within sections[type]. For example, /gmu/yjs/zsgz/pyxz fails because 'pyxz' is not a valid subtype under 'zsgz' (it belongs to 'xzzx'). Not every subtype is valid for every type.","commonSituations":"Mixing a valid type with a subtype from a different section (e.g., zsgz/pyxz); typos in path segments; guessing subtypes that don't exist for a given type.","solutions":["Refer to the sections object in the source for the exact type/subtype matrix — only specific combinations are valid","Use the documented example: /gmu/yjs/zsgz/tzgg","Check the route parameters options declaration which lists all valid type and subtype values"],"exampleFix":"// before\nif (!Object.hasOwn(sections, type) || !Object.hasOwn(sections[type], subtype)) {\n    throw new Error('Invalid type or subtype');\n}\n\n// after (use InvalidParameterError with guidance)\nimport InvalidParameterError from '@/errors/types/invalid-parameter';\n// ...\nif (!Object.hasOwn(sections, type) || !Object.hasOwn(sections[type], subtype)) {\n    throw new InvalidParameterError(`Invalid type '${type}' or subtype '${subtype}'. See route documentation for valid combinations.`);\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isValidSection(type: string, subtype: string): boolean {\n    return Object.hasOwn(sections, type) && Object.hasOwn(sections[type], subtype);\n}\n\n// Usage in handler:\nconst { type, subtype } = ctx.req.param();\nif (!isValidSection(type, subtype)) {\n    throw new InvalidParameterError(`Invalid type/subtype combination: ${type}/${subtype}`);\n}","tryCatchPattern":null,"preventionTips":["Remember that not every subtype is valid for every type — check the nested sections object","Use the documented example as a baseline: zsgz/tzgg","Consider validating type and subtype independently to give more specific error messages"],"tags":["validation","parameter","invalid-parameter","nested-validation"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}