DIYgod/RSSHub · error · Error

Invalid category: ${finalSearchParams.category}

Error message

Invalid category: ${finalSearchParams.category}

What it means

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.

Source

Thrown at lib/routes/voronoiapp/common.ts:41

        limit: 20,
        offset: 0,
        ...params,
    };
    if (finalSearchParams.time_range !== undefined) {
        finalSearchParams.time_range = finalSearchParams.time_range.toUpperCase();
        if (TimeRangeParam.options.every((option) => option.value !== finalSearchParams.time_range)) {
            throw new Error(`Invalid time range: ${finalSearchParams.time_range}`);
        }
        // The Voronoi API doesn't support "ALL"
        if (finalSearchParams.time_range === 'ALL') {
            finalSearchParams.time_range = undefined;
        }
    }
    if (finalSearchParams.category !== undefined && finalSearchParams.category !== null) {
        const category = finalSearchParams.category;
        finalSearchParams.category = CategoryParam.options.find((option) => option.value.toLowerCase() === category.toLowerCase())?.value;
        if (finalSearchParams.category === undefined) {
            throw new Error(`Invalid category: ${finalSearchParams.category}`);
        }
    }
    if (finalSearchParams.tab !== undefined && finalSearchParams.tab !== null) {
        finalSearchParams.tab = finalSearchParams.tab.toUpperCase();
        if (!Object.values(TabMap).includes(finalSearchParams.tab)) {
            throw new Error(`Invalid tab: ${finalSearchParams.tab}`);
        }
    }
    for (const key in finalSearchParams) {
        if (finalSearchParams[key] !== undefined && finalSearchParams[key] !== null) {
            url.searchParams.set(key, finalSearchParams[key]);
        }
    }
    const data = await ofetch<Post[]>(url.href);
    const items: DataItem[] = data.map((post) => ({
        title: post.headline,
        link: `https://www.voronoiapp.com/${post.category.split(' ').join('-').toLowerCase()}/${post.link}`,
        pubDate: parseDate(post.published_at),

View on GitHub (pinned to bed535e087)

Solutions

  1. Use one of the canonical category values from `CategoryParam.options` (e.g. `Sports`, `Technology`, `Economy`) — these are case-insensitive.
  2. Omit the category or pass an empty string to get all categories.
  3. If maintaining this route, fix the error message to use the captured local `category` variable instead of the already-overwritten `finalSearchParams.category`.

Example fix

// before (bug: message shows 'undefined' because finalSearchParams.category was overwritten)
const category = finalSearchParams.category;
finalSearchParams.category = CategoryParam.options.find(
    (option) => option.value.toLowerCase() === category.toLowerCase()
)?.value;
if (finalSearchParams.category === undefined) {
    throw new Error(`Invalid category: ${finalSearchParams.category}`);
}
// after (use original value in message)
if (finalSearchParams.category === undefined) {
    throw new Error(`Invalid category: ${category}`);
}
Defensive patterns

Strategy: validation

Validate before calling

const VALID_CATEGORIES = CategoryParam.options.map((o) => o.value.toLowerCase());
if (category && !VALID_CATEGORIES.includes(category.toLowerCase())) {
    throw new InvalidParameterError(
        `Invalid category: ${category}. Valid: ${CategoryParam.options.map((o) => o.value).join(', ')}`
    );
}

Type guard

function isValidVoronoiCategory(cat: string): boolean {
    return CategoryParam.options.some(
        (option) => option.value.toLowerCase() === cat.toLowerCase()
    );
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12). Data as JSON: /api/errors/e53721985dc1c07c. Report an issue: GitHub.