{"record":{"id":"f18c8bf1f3d80cd9","repo":"DIYgod/RSSHub","slug":"unknown-category-category-supported-object","errorCode":null,"errorMessage":"Unknown category: ${category}. Supported: ${Object.keys(APP_CATEGORY_MAP).join(', ')}","messagePattern":"Unknown category: (.+?)\\. Supported: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"warning","filePath":"lib/routes/theinitium/app.ts","lineNumber":104,"sourceCode":"| 速递  | whats\\\\_new\\\\_sc    | whats\\\\_new\\\\_tc    |\n| 专题  | report\\\\_sc        | report\\\\_tc        |\n| 评论  | opinion\\\\_sc       | opinion\\\\_tc       |\n| 国际  | international\\\\_sc | international\\\\_tc |\n| 大陆  | mainland\\\\_sc      | mainland\\\\_tc      |\n| 香港  | hongkong\\\\_sc      | hongkong\\\\_tc      |\n| 台湾  | taiwan\\\\_sc        | taiwan\\\\_tc        |\n\n::: tip\n原 App 路由已迁移至 Ghost CMS API。播客（article\\\\_audio）分类已停用，请改用 \\`/theinitium/channel\\` 路由。\n:::`,\n};\n\nasync function handler(ctx) {\n    const category = ctx.req.param('category') ?? 'latest_sc';\n\n    const mapping = APP_CATEGORY_MAP[category];\n    if (!mapping) {\n        throw new Error(`Unknown category: ${category}. Supported: ${Object.keys(APP_CATEGORY_MAP).join(', ')}`);\n    }\n\n    const { channelType, language } = mapping;\n\n    // Reason: Reuse the same Ghost tag filter logic as processFeed's channel case\n    const baseTag = CHANNEL_TAG_MAP[channelType] ?? channelType;\n    let filter = '';\n    if (baseTag === '') {\n        // \"latest\" = no tag filter, just filter by language via internal tag\n        filter = `tag:hash-${language}`;\n    } else {\n        const tagSlug = applyLanguageToTagSlug(baseTag, language);\n        filter = `tag:${tagSlug}`;\n    }\n\n    const params: Record<string, string> = {\n        include: 'tags,authors',\n        limit: '20',","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/theinitium/app.ts#L86-L122","documentation":"The theinitium app route maps the :category path param through APP_CATEGORY_MAP to a {channelType, language} pair. If the provided category is not a key in that map, it throws an Error listing the supported keys, so the caller knows which values are accepted.","triggerScenarios":"Requesting /theinitium/app/<category> with a category that is not one of the predefined keys (e.g. an old or typo'd channel name). The default category is 'latest_sc'.","commonSituations":"User copies a channel name from the website that is not in APP_CATEGORY_MAP; the map was refactored and a previously-valid category was removed/renamed; typo in the URL.","solutions":["Use one of the categories listed in the error message (the keys of APP_CATEGORY_MAP).","Omit the category to fall back to the default 'latest_sc'.","If a real channel is missing, add it to APP_CATEGORY_MAP with the correct channelType and language."],"exampleFix":"// before\nconst mapping = APP_CATEGORY_MAP[category];\nif (!mapping) {\n    throw new Error(`Unknown category: ${category}. Supported: ${Object.keys(APP_CATEGORY_MAP).join(', ')}`);\n}\n\n// after: throw an InvalidParameterError (RSS idiom) and hint the default\nconst mapping = APP_CATEGORY_MAP[category];\nif (!mapping) {\n    throw new InvalidParameterError(`Unknown category \"${category}\". Supported: ${Object.keys(APP_CATEGORY_MAP).join(', ')} (default: latest_sc)`);\n}","handlingStrategy":"validation","validationCode":"const SUPPORTED = new Set(Object.keys(APP_CATEGORY_MAP));\nfunction isSupportedCategory(c: string): boolean {\n    return SUPPORTED.has(c);\n}\n// expose valid categories via the route docs; default to 'latest_sc'","typeGuard":"function isAppCategory(c: string): c is keyof typeof APP_CATEGORY_MAP {\n    return c in APP_CATEGORY_MAP;\n}","tryCatchPattern":"try {\n    return await handler(ctx);\n} catch (e) {\n    if (e instanceof Error && /Unknown category/.test(e.message)) {\n        return badRequest(`Use one of: ${Object.keys(APP_CATEGORY_MAP).join(', ')}`);\n    }\n    throw e;\n}","preventionTips":["Use a category from APP_CATEGORY_MAP; omit the param to default to 'latest_sc'.","Keep the map and its documentation in sync when categories are added/renamed.","Type category as keyof typeof APP_CATEGORY_MAP so invalid values fail at compile time."],"tags":["validation","parameter","theinitium"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}