{"record":{"id":"e53721985dc1c07c","repo":"DIYgod/RSSHub","slug":"invalid-category-finalsearchparams-category","errorCode":null,"errorMessage":"Invalid category: ${finalSearchParams.category}","messagePattern":"Invalid category: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/voronoiapp/common.ts","lineNumber":41,"sourceCode":"        limit: 20,\n        offset: 0,\n        ...params,\n    };\n    if (finalSearchParams.time_range !== undefined) {\n        finalSearchParams.time_range = finalSearchParams.time_range.toUpperCase();\n        if (TimeRangeParam.options.every((option) => option.value !== finalSearchParams.time_range)) {\n            throw new Error(`Invalid time range: ${finalSearchParams.time_range}`);\n        }\n        // The Voronoi API doesn't support \"ALL\"\n        if (finalSearchParams.time_range === 'ALL') {\n            finalSearchParams.time_range = undefined;\n        }\n    }\n    if (finalSearchParams.category !== undefined && finalSearchParams.category !== null) {\n        const category = finalSearchParams.category;\n        finalSearchParams.category = CategoryParam.options.find((option) => option.value.toLowerCase() === category.toLowerCase())?.value;\n        if (finalSearchParams.category === undefined) {\n            throw new Error(`Invalid category: ${finalSearchParams.category}`);\n        }\n    }\n    if (finalSearchParams.tab !== undefined && finalSearchParams.tab !== null) {\n        finalSearchParams.tab = finalSearchParams.tab.toUpperCase();\n        if (!Object.values(TabMap).includes(finalSearchParams.tab)) {\n            throw new Error(`Invalid tab: ${finalSearchParams.tab}`);\n        }\n    }\n    for (const key in finalSearchParams) {\n        if (finalSearchParams[key] !== undefined && finalSearchParams[key] !== null) {\n            url.searchParams.set(key, finalSearchParams[key]);\n        }\n    }\n    const data = await ofetch<Post[]>(url.href);\n    const items: DataItem[] = data.map((post) => ({\n        title: post.headline,\n        link: `https://www.voronoiapp.com/${post.category.split(' ').join('-').toLowerCase()}/${post.link}`,\n        pubDate: parseDate(post.published_at),","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/voronoiapp/common.ts#L23-L59","documentation":"Thrown by the Voronoi `getPostItems` helper when the `category` parameter does not match (case-insensitively) any option value in `CategoryParam.options`. Note a bug: line 39 reassigns `finalSearchParams.category` to `undefined` when the `.find()` fails, so the error message on line 41 always reads `Invalid category: undefined` regardless of what the user actually passed — the original value was captured in the local `category` variable on line 38 but is not used in the message.","triggerScenarios":"Calling `getPostItems({ category: 'NonExistentCategory' })` or passing a category label (like 'Sports Data Insights') instead of the option value ('Sports'). The category must match one of the ~25 defined option values case-insensitively.","commonSituations":"User passes a display label instead of the canonical value, or a category that was removed from the Voronoi taxonomy. The misleading error message ('undefined') makes diagnosis harder — the user sees 'Invalid category: undefined' even when they passed a real string.","solutions":["Use one of the canonical category values from `CategoryParam.options` (e.g. `Sports`, `Technology`, `Economy`) — these are case-insensitive.","Omit the category or pass an empty string to get all categories.","If maintaining this route, fix the error message to use the captured local `category` variable instead of the already-overwritten `finalSearchParams.category`."],"exampleFix":"// before (bug: message shows 'undefined' because finalSearchParams.category was overwritten)\nconst category = finalSearchParams.category;\nfinalSearchParams.category = CategoryParam.options.find(\n    (option) => option.value.toLowerCase() === category.toLowerCase()\n)?.value;\nif (finalSearchParams.category === undefined) {\n    throw new Error(`Invalid category: ${finalSearchParams.category}`);\n}\n// after (use original value in message)\nif (finalSearchParams.category === undefined) {\n    throw new Error(`Invalid category: ${category}`);\n}","handlingStrategy":"validation","validationCode":"const VALID_CATEGORIES = CategoryParam.options.map((o) => o.value.toLowerCase());\nif (category && !VALID_CATEGORIES.includes(category.toLowerCase())) {\n    throw new InvalidParameterError(\n        `Invalid category: ${category}. Valid: ${CategoryParam.options.map((o) => o.value).join(', ')}`\n    );\n}","typeGuard":"function isValidVoronoiCategory(cat: string): boolean {\n    return CategoryParam.options.some(\n        (option) => option.value.toLowerCase() === cat.toLowerCase()\n    );\n}","tryCatchPattern":null,"preventionTips":["Fix the bug: capture the original value in a local variable BEFORE overwriting finalSearchParams.category, and use it in the error message.","Use option .value (e.g. 'Sports'), not option .label (e.g. 'Sports Data Insights...').","Use InvalidParameterError instead of generic Error for user-correctable input errors."],"tags":["parameter-validation","voronoiapp","rss-route","enum-validation","bug-error-message"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}