{"record":{"id":"3e94fd33e4a435cd","repo":"DIYgod/RSSHub","slug":"invalid-tab-finalsearchparams-tab","errorCode":null,"errorMessage":"Invalid tab: ${finalSearchParams.tab}","messagePattern":"Invalid tab: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/voronoiapp/common.ts","lineNumber":47,"sourceCode":"        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),\n        description: `<img src=\"https://cdn.voronoiapp.com/public/${post.webp_image}\" />\n        ${post.description}`,\n        image: `https://cdn.voronoiapp.com/public/${post.webp_image}`,\n        author: post.author.first_name + ' ' + post.author.last_name,\n        updated: parseDate(post.updated_at),\n        category: [post.category],","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/voronoiapp/common.ts#L29-L65","documentation":"Thrown by the Voronoi `getPostItems` helper when the `tab` parameter, after uppercasing, is not one of the values in the `TabMap` object (`POPULAR`, `DISCUSSED`, `VIEWED`). The check uses `Object.values(TabMap).includes()`. This is a generic `Error`. Note the `TabMap` keys are lowercase kebab (`most-popular`) but the values are uppercase (`POPULAR`) — this validation checks the value side.","triggerScenarios":"Calling `getPostItems({ tab: 'TRENDING' })` or any uppercase string not in `TabMap`'s values. In the popular route, the `tab` path parameter is mapped from its lowercase key (e.g. `most-popular`) to its uppercase value (e.g. `POPULAR`) before calling `getPostItems`, so a valid popular-route tab should always pass this check — unless `getPostItems` is called directly with a bad value.","commonSituations":"A code change in the popular route passes an unmapped tab value, or a developer calls `getPostItems` directly with a raw user input. The popular route (line 34) has its own separate `Object.hasOwn(TabMap, ...)` check that guards against this before the mapping.","solutions":["Use one of `POPULAR`, `DISCUSSED`, or `VIEWED` as the tab value (uppercase).","In the popular route, use the lowercase path keys: `most-popular`, `most-discussed`, `most-viewed`.","If calling `getPostItems` directly, map through `TabMap` first."],"exampleFix":"// before\ntab: 'TRENDING'\n// after\ntab: TabMap['most-popular']  // 'POPULAR'","handlingStrategy":"validation","validationCode":"const VALID_TABS = Object.values(TabMap); // ['POPULAR', 'DISCUSSED', 'VIEWED']\nif (tab && !VALID_TABS.includes(tab.toUpperCase())) {\n    throw new InvalidParameterError(`Invalid tab: ${tab}. Valid: ${VALID_TABS.join(', ')}`);\n}","typeGuard":"function isValidTabValue(tab: string): tab is 'POPULAR' | 'DISCUSSED' | 'VIEWED' {\n    return Object.values(TabMap).includes(tab.toUpperCase() as any);\n}","tryCatchPattern":null,"preventionTips":["Always route user-supplied tab values through TabMap mapping before calling getPostItems.","Prefer the route-level guard (Object.hasOwn on TabMap keys) over relying on the helper's value-level check."],"tags":["parameter-validation","voronoiapp","rss-route","enum-validation"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}