DIYgod/RSSHub · error · InvalidParameterError

Invalid subsite: ${sub}

Error message

Invalid subsite: ${sub}

What it means

Thrown by syosetu/ranking-r18.ts:167 as an InvalidParameterError when the `sub` path param is not a key of syosetuSubToNocgenre (types/ranking-r18.ts:25). Valid R18 subsites: noc (Nocturne), mnlt (Moonlight), mnlt-bl (Moonlight BL), mid (Midnight). NOTE the footgun: mnlt-bl IS valid here because ranking-r18.ts's SyosetuSub enum includes MOONLIGHT_BL, but search.ts's SyosetuSub enum does NOT — the same-named enum has different members across files. The check runs AFTER parseRankingType, so an invalid `type` throws first.

Source

Thrown at lib/routes/syosetu/ranking-r18.ts:167

    const rankingUrl = `${baseUrl}/rank/list/type/${type}`;
    const api = new NarouNovelFetch();

    const limit = Math.min(Number(ctx.req.query('limit') ?? 300), 300);
    const { period, novelType } = parseRankingType(type);

    const searchParams: SearchParams = {
        gzip: 5,
        lim: limit,
        order: periodToOrder[period],
    };

    // TOTAL: Skip type filter to get all types combined
    if (novelType !== NovelType.TOTAL) {
        searchParams.type = novelType;
    }

    if (!Object.hasOwn(syosetuSubToNocgenre, sub)) {
        throw new InvalidParameterError(`Invalid subsite: ${sub}`);
    }
    const nocgenre = syosetuSubToNocgenre[sub];

    const builder = new SearchBuilderR18(searchParams, api).r18Site(nocgenre);
    const result = await builder.execute();

    const items = result.values.map((novel, index) => ({
        title: `#${index + 1} ${novel.title}`,
        link: `https://novel18.syosetu.com/${String(novel.ncode).toLowerCase()}`,
        description: renderDescription({ novel }),
        author: novel.writer,
        category: novel.keyword.split(/[\s/\u{FF0F}]/u).filter(Boolean),
    }));

    return {
        title: `小説家になろう (${sub}) - ${getRankingTitle(type, limit)}`,
        link: rankingUrl,
        item: items as DataItem[],

View on GitHub (pinned to bed535e087)

Solutions

  1. Use noc, mnlt, mnlt-bl, or mid (lowercase, hyphenated exactly where shown).
  2. Remember mnlt-bl is valid ONLY in the rankingr18 route — not in the search route.

Example fix

// before
GET /syosetu/rankingr18/mnltbl/daily_total
// after
GET /syosetu/rankingr18/mnlt-bl/daily_total
Defensive patterns

Strategy: validation

Validate before calling

import { syosetuSubToNocgenre } from './types/ranking-r18';

function isValidR18Sub(sub: string): boolean {
  return Object.hasOwn(syosetuSubToNocgenre, sub);
}

Type guard

import { SyosetuSub } from './types/ranking-r18';

const VALID_R18_SUBS = Object.values(SyosetuSub); // noc, mnlt, mnlt-bl, mid

function isR18Sub(sub: string): sub is SyosetuSub {
  return (VALID_R18_SUBS as readonly string[]).includes(sub);
}

Prevention

When it happens

Trigger: /syosetu/rankingr18/<sub>/<type> with sub not in {noc, mnlt, mnlt-bl, mid}: typos like 'mnltbl' (missing hyphen), 'nocturne', 'moonlight', or 'bl' alone.

Common situations: Using the full site name instead of the code; forgetting the hyphen in mnlt-bl; assuming the subsite code set is identical across all syosetu routes.

Related errors


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