{"record":{"id":"16410c3f759fb412","repo":"DIYgod/RSSHub","slug":"invalid-category-category-16410c","errorCode":null,"errorMessage":"Invalid category: ${category}","messagePattern":"Invalid category: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/lemonde/index.ts","lineNumber":80,"sourceCode":"| societe       | Society                |\n| culture       | Culture                |\n| sport         | Sports                 |\n| planete       | Environment            |\n| pixels        | Tech / Digital         |\n| sciences      | Sciences               |\n| idees         | Opinions               |\n| sante         | Health                 |\n| em            | M le mag               |\n| en-continu    | Live / Breaking        |\n| decodeurs     | Fact-checking          |`,\n};\n\nasync function handler(ctx) {\n    const category = ctx.req.param('category') ?? '';\n    const feedUrl = feedMap[category];\n\n    if (!feedUrl) {\n        throw new Error(`Invalid category: ${category}`);\n    }\n\n    const xml = await ofetch(feedUrl);\n    const $ = load(xml, { xml: true });\n\n    const channel = $('channel');\n    const feedTitle = channel.children('title').text();\n    const feedLink = channel.children('link').text() || ROOT_URL;\n\n    const limit = ctx.req.query('limit') ? Number(ctx.req.query('limit')) : 20;\n\n    const items = $('item')\n        .toArray()\n        .slice(0, limit)\n        .map((el) => {\n            const item = $(el);\n            const link = item.children('link').text() || item.children('guid').text();\n            const title = item.children('title').text();","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/lemonde/index.ts#L62-L98","documentation":"Thrown by the Le Monde route handler when the `:category` path parameter does not match any key in the static `feedMap` object (lib/routes/lemonde/index.ts:10). The handler resolves the category to an RSS XML URL via a dictionary lookup; an unknown slug yields `feedUrl === undefined`, so it aborts before any network call. Valid keys are the slugs listed in the route description (e.g. `international`, `politique`, `economie`, `societe`, `culture`, `sport`, `planete`, `pixels`, `sciences`, `idees`, `sante`, `em`, `en-continu`, `decodeurs`, or empty for the homepage).","triggerScenarios":"Requesting `/lemonde/<slug>` where `<slug>` is misspelled, uppercase, or not in `feedMap` — e.g. `/lemonde/world`, `/lemonde/Politics`, `/lemonde/economy`. Also triggered when the radar rule rewrites a source URL whose path segment is not a known slug.","commonSituations":"Users guessing English category names instead of the French slugs; copy-paste of a URL path that includes a trailing segment the map does not cover; radar auto-derivation from `lemonde.fr/<section>` where `<section>` is an article or non-feed section.","solutions":["Use one of the documented slugs from the route table (e.g. `/lemonde/international`, `/lemonde/sport`) or omit the category for the homepage feed.","If you need a new section, add its slug and RSS URL to the `feedMap` dictionary in lib/routes/lemonde/index.ts:10 and rebuild.","Verify the spelling and case — keys are lowercase and use hyphens (e.g. `en-continu`, not `EnContinu`)."],"exampleFix":"// before: GET /lemonde/world  -> throws\n// after:  GET /lemonde/international","handlingStrategy":"validation","validationCode":"const LEMONDE_CATEGORIES = ['', 'international', 'politique', 'economie', 'societe', 'culture', 'sport', 'planete', 'pixels', 'sciences', 'idees', 'sante', 'em', 'en-continu', 'decodeurs'];\nfunction isValidLeMondeCategory(category: string): boolean {\n    return LEMONDE_CATEGORIES.includes(category);\n}\n// before requesting: if (!isValidLeMondeCategory(slug)) return badRequest();","typeGuard":"function isLeMondeCategory(value: string): value is '' | 'international' | 'politique' | 'economie' | 'societe' | 'culture' | 'sport' | 'planete' | 'pixels' | 'sciences' | 'idees' | 'sante' | 'em' | 'en-continu' | 'decodeurs' {\n    return value === '' || LEMONDE_CATEGORIES.includes(value);\n}","tryCatchPattern":"// Match the dynamic message shape; surface a clean 400 to the caller.\ntry {\n    await fetchRSS('/lemonde/' + slug);\n} catch (e) {\n    if (e instanceof Error && /^Invalid category:/.test(e.message)) {\n        throw new TypeError(`Unknown Le Monde category '${slug}'`);\n    }\n    throw e;\n}","preventionTips":["Derive the valid set from `feedMap` (Object.keys) so docs and validation never drift.","Expose the category list in your route's `parameters` description so users see valid values.","Normalize input (trim, lowercase) before lookup."],"tags":["invalid-input","route-parameter","rss-feed"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}