{"record":{"id":"05f396bdf611ec82","repo":"DIYgod/RSSHub","slug":"invalid-category-category-05f396","errorCode":null,"errorMessage":"Invalid category: ${category}","messagePattern":"Invalid category: (.+?)","errorType":"validation","errorClass":"InvalidParameterError","httpStatus":503,"severity":"warning","filePath":"lib/routes/plurk/top.ts","lineNumber":39,"sourceCode":"        supportPodcast: false,\n        supportScihub: false,\n    },\n    name: 'Top',\n    maintainers: ['TonyRL'],\n    handler,\n    description: `| Top Replurks | Top Favorites | Top Responded |\n| ------------ | ------------- | ------------- |\n| topReplurks  | topFavorites  | topResponded  |\n\n| English | 中文（繁體） |\n| ------- | ------------ |\n| en      | zh           |`,\n};\n\nasync function handler(ctx) {\n    const { category = 'topReplurks', lang = 'en' } = ctx.req.param();\n    if (!categoryList.has(category)) {\n        throw new InvalidParameterError(`Invalid category: ${category}`);\n    }\n\n    const { data: apiResponse } = await got(`${baseUrl}/Stats/${category}`, {\n        searchParams: {\n            period: 'day',\n            lang,\n            limit: ctx.req.query('limit') ? Number(ctx.req.query('limit')) : 90,\n        },\n    });\n\n    const items = await Promise.all(apiResponse.stats.map((item) => item[1]).map((item) => getPlurk(`plurk:${item.plurk_id}`, item, item.owner.display_name)));\n\n    return {\n        title: 'Top Plurk - Plurk',\n        image: 'https://s.plurk.com/2c1574c02566f3b06e91.png',\n        link: `${baseUrl}/top#${category}`,\n        item: items,\n        language: lang,","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/plurk/top.ts#L21-L57","documentation":"InvalidParameterError thrown by the Plurk Top handler when the category path parameter is not in the allowed set {topReplurks, topFavorites, topResponded}. The route validates against a Set before building the /Stats/{category} URL, so an unknown category never reaches the upstream API.","triggerScenarios":"Passing a category value outside the three valid ones in /plurk/top/:category?/:lang?, e.g. a typo like 'topReplurk' (missing s), 'topLikes', or a localized string.","commonSituations":"User mistypes the category; copies a value from outdated docs; uses a singular form; passes an arbitrary string hoping for a category.","solutions":["Use one of the documented categories: topReplurks, topFavorites, or topResponded (case-sensitive).","Omit the category to accept the default (topReplurks).","If subscribing from a docs example, copy the value verbatim.","Update any stale RSS client URLs that reference a renamed/removed category."],"exampleFix":"// before: /plurk/top/topReplurk\n// after:  /plurk/top/topReplurks","handlingStrategy":"validation","validationCode":"const VALID_CATEGORIES = new Set(['topReplurks', 'topFavorites', 'topResponded']);\nfunction isValidCategory(c: string): c is 'topReplurks' | 'topFavorites' | 'topResponded' {\n  return VALID_CATEGORIES.has(c);\n}\n// before building the request:\nif (!isValidCategory(category)) {\n  // reject with the allowed list\n}","typeGuard":"const isValidCategory = (c: unknown): c is 'topReplurks' | 'topFavorites' | 'topResponded' =>\n  typeof c === 'string' && new Set(['topReplurks', 'topFavorites', 'topResponded']).has(c as any);","tryCatchPattern":"try {\n  // plurk top handler\n} catch (e) {\n  if (e instanceof InvalidParameterError && /Invalid category/.test(e.message)) {\n    // surface the three valid categories to the user\n  }\n}","preventionTips":["Constrain category input to the documented Set before requesting.","Default the category when omitted to avoid typos.","Keep the category list and the route description table in sync."],"tags":["plurk","invalid-parameter","validation","category"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}