{"record":{"id":"5ce883708931db5e","repo":"DIYgod/RSSHub","slug":"invalid-ranking-type-type","errorCode":null,"errorMessage":"Invalid ranking type: ${type}","messagePattern":"Invalid ranking type: (.+?)","errorType":"validation","errorClass":"InvalidParameterError","httpStatus":503,"severity":"error","filePath":"lib/routes/syosetu/ranking-r18.ts","lineNumber":132,"sourceCode":"        },\n        {\n            source: ['mnlt.syosetu.com/rank/bllist/type/:type'],\n            target: '/rankingr18/mnlt-bl/:type',\n        },\n        ...getBest5RadarItems(),\n    ],\n};\n\nfunction parseRankingType(type: string): { period: RankingPeriod; novelType: NovelType } {\n    const [periodStr, novelTypeStr] = type.split('_', 2);\n\n    const period = periodStr as RankingPeriod;\n    const novelType = novelTypeStr as NovelType;\n\n    const isValid = [Object.values(RankingPeriod).includes(period), Object.values(NovelType).includes(novelType)].every(Boolean);\n\n    if (!isValid) {\n        throw new InvalidParameterError(`Invalid ranking type: ${type}`);\n    }\n\n    return {\n        period: periodStr as RankingPeriod,\n        novelType: novelTypeStr as NovelType,\n    };\n}\n\nfunction getRankingTitle(type: string, limit: number): string {\n    const { period, novelType } = parseRankingType(type);\n    return `${periodToJapanese[period]}${novelTypeToJapanese[novelType]}ランキング BEST${limit}`;\n}\n\nasync function handler(ctx: Context): Promise<Data> {\n    const { sub, type } = ctx.req.param();\n    const baseUrl = `https://${sub === SyosetuSub.MOONLIGHT_BL ? SyosetuSub.MOONLIGHT : sub}.syosetu.com`;\n    const rankingUrl = `${baseUrl}/rank/list/type/${type}`;\n    const api = new NarouNovelFetch();","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/syosetu/ranking-r18.ts#L114-L150","documentation":"Thrown by parseRankingType (syosetu/ranking-r18.ts:132) as an InvalidParameterError when the R18 ranking `type` (format period_novelType) has an invalid component. CRITICAL difference from the general ranking: the R18 RankingPeriod enum (types/ranking-r18.ts:10) EXCLUDES 'total' — valid R18 periods are daily, weekly, monthly, quarter, yearly only. novelType (NovelType) is the same: total, t, r, er. Reached via /syosetu/rankingr18/<sub>/<type>. The R18 enum is file-local and looks nearly identical to the general one, which is the main footgun.","triggerScenarios":"Using 'total' as the period (e.g. total_t or total_total) — not supported on R18 sites; wrong segment order (t_daily); unknown novelType; missing the novelType segment.","commonSituations":"Copying a general-ranking URL (/ranking/list/total_total) into the r18 route; assuming the two RankingPeriod enums are the same.","solutions":["Use a valid R18 period — daily, weekly, monthly, quarter, or yearly — never 'total'.","Keep the <period>_<novelType> order, with novelType in {total, t, r, er}."],"exampleFix":"// before (total period is invalid for R18)\nGET /syosetu/rankingr18/noc/total_total\n// after\nGET /syosetu/rankingr18/noc/daily_total","handlingStrategy":"validation","validationCode":"import { RankingPeriod, NovelType } from './types/ranking-r18';\n\n// R18 RankingPeriod EXCLUDES 'total' — do not import the general one by mistake.\nconst PERIODS = Object.values(RankingPeriod);\nconst NOVEL_TYPES = Object.values(NovelType);\n\nfunction isValidR18Type(type: string): boolean {\n  const [p, n] = type.split('_', 2);\n  return PERIODS.includes(p as RankingPeriod)\n    && NOVEL_TYPES.includes(n as NovelType);\n}","typeGuard":"function isR18RankingType(type: string): boolean {\n  const [p, n] = type.split('_', 2);\n  return ['daily','weekly','monthly','quarter','yearly'].includes(p) // NO 'total'\n    && ['total','t','r','er'].includes(n);\n}","tryCatchPattern":null,"preventionTips":["Never use 'total' as the period in an R18 ranking URL — it is only valid in the general ranking.","Remember the R18 RankingPeriod enum is file-local and a strict subset of the general one.","Keep the <period>_<novelType> order."],"tags":["invalid-parameter","enum","syosetu","ranking","r18"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}