{"record":{"id":"77ead6e579a92882","repo":"DIYgod/RSSHub","slug":"invalid-category-77ead6","errorCode":null,"errorMessage":"Invalid category","messagePattern":"Invalid category","errorType":"validation","errorClass":"InvalidParameterError","httpStatus":null,"severity":"warning","filePath":"lib/routes/linkresearcher/index.tsx","lineNumber":63,"sourceCode":"        name: '文章',\n    },\n    'zh-TW': {\n        name: '文章',\n    },\n};\n\nasync function handler(ctx: Context): Promise<Data> {\n    const categoryMap = { theses: '论文', information: '新闻', careers: '职业' } as const;\n    const params = ctx.req.param('params');\n    const filters = new URLSearchParams(params);\n\n    const subject = filters.get('subject');\n    const columns = filters.get('columns');\n    const query = filters.get('query') ?? '';\n    const category = filters.get('category') ?? ('theses' as keyof typeof categoryMap);\n\n    if (!Object.hasOwn(categoryMap, category)) {\n        throw new InvalidParameterError('Invalid category');\n    }\n    let title = categoryMap[category] as string;\n\n    const token = crypto.randomUUID();\n\n    const data: {\n        filters: {\n            status: boolean;\n            subject?: string;\n            columns?: string;\n        };\n    } = { filters: { status: true } };\n\n    if (subject) {\n        data.filters.subject = subject;\n        title += `「${subject}」`;\n    }\n","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/linkresearcher/index.tsx#L45-L81","documentation":"Thrown by the LinkResearcher (领研) route when the category query parameter is not one of 'theses', 'information', or 'careers'. The category is extracted from a URLSearchParams string in the :params path segment (format: category=theses&subject=...). Object.hasOwn(categoryMap, category) guards the lookup.","triggerScenarios":"Calling the route with category=news, category=papers, or any value outside the three allowed keys. Also fires when the params string omits category entirely — but the default 'theses' prevents that; only an explicitly invalid value triggers it.","commonSituations":"User guesses a category name instead of consulting the docs. A user passes 'paper' (singular) instead of 'theses'. The site adds a new category and the route map is not updated.","solutions":["Use only 'theses', 'information', or 'careers' as the category value.","List valid categories in the error message.","If the params string is malformed (missing =), URLSearchParams.get returns null and the default kicks in — so the error specifically means an explicit-but-wrong value."],"exampleFix":"// before\nif (!Object.hasOwn(categoryMap, category)) {\n    throw new InvalidParameterError('Invalid category');\n}\n\n// after\nconst validCategories = Object.keys(categoryMap);\nif (!validCategories.includes(category)) {\n    throw new InvalidParameterError(`Invalid category '${category}'. Supported: ${validCategories.join(', ')}`);\n}","handlingStrategy":"validation","validationCode":"const categoryMap = { theses: '论文', information: '新闻', careers: '职业' } as const;\nconst validCategories = Object.keys(categoryMap);\nconst category = filters.get('category') ?? 'theses';\nif (!validCategories.includes(category)) {\n    throw new InvalidParameterError(`Invalid category '${category}'. Supported: ${validCategories.join(', ')}`);\n}","typeGuard":"function isLinkResearcherCategory(c: string): c is keyof typeof categoryMap {\n    return c in categoryMap;\n}","tryCatchPattern":null,"preventionTips":["Derive valid categories from the categoryMap keys so validation never drifts from the map.","Include the valid list in the error message.","Remember the default is 'theses' — an explicit invalid value is required to trigger this.","If the site adds a category, add it to categoryMap and it is automatically accepted."],"tags":["validation","parameter","linkresearcher","query-string"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}