DIYgod/RSSHub · warning · InvalidParameterError

Invalid period: ${period}

Error message

Invalid period: ${period}

What it means

Thrown by handleIsekaiRanking (syosetu/ranking-isekai.ts:72) as an InvalidParameterError when periodToPointField[period] is falsy. periodToPointField (types/ranking.ts:32) has entries for ALL six RankingPeriod values, so in the normal flow this is UNREACHABLE — parseIsekaiRankingType already validated period. It is a defensive guard against periodToPointField and the RankingPeriod enum drifting out of sync (a new period added to the enum but not to the lookup map).

Source

Thrown at lib/routes/syosetu/ranking-isekai.ts:72

    return searchParams;
}

export async function handleIsekaiRanking(type: string, limit: number): Promise<Data> {
    const { period, category, novelType } = parseIsekaiRankingType(type);
    const rankingUrl = `https://yomou.syosetu.com/rank/isekailist/type/${type}`;
    const rankingTitle = `[${periodToJapanese[period]}] 異世界転生/転移${isekaiCategoryToJapanese[category]}ランキング - ${novelTypeToJapanese[novelType]} BEST${limit}`;

    const searchParams = getIsekaiSearchParams(period, category, novelType, limit);
    const api = new NarouNovelFetch();

    const [tenseiResult, tenniResult] = await Promise.all([new SearchBuilder({ ...searchParams, istensei: 1 }, api).execute(), new SearchBuilder({ ...searchParams, istenni: 1 }, api).execute()]);

    const combinedNovels = [...tenseiResult.values, ...tenniResult.values];
    const uniqueNovels = new Map(combinedNovels.map((novel) => [novel.ncode, novel])).values().toArray();

    const pointField = periodToPointField[period];
    if (!pointField) {
        throw new InvalidParameterError(`Invalid period: ${period}`);
    }

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

    return {
        title: `小説家になろう - ${rankingTitle}`,
        link: rankingUrl,
        item: items.slice(0, limit) as DataItem[],
        language: 'ja',
    };

View on GitHub (pinned to bed535e087)

Solutions

  1. When adding a RankingPeriod, update ALL four maps in types/ranking.ts: periodToOrder, periodToPointField, periodToJapanese, and any downstream usage.
  2. Do not bypass parseIsekaiRankingType when invoking handleIsekaiRanking.

Example fix

// before: new period 'alltime' added to RankingPeriod but not periodToPointField
// after: add the mapping
export const periodToPointField = {
    ...
    [RankingPeriod.ALLTIME]: 'alltime_point',
} as const;
Defensive patterns

Strategy: validation

Validate before calling

import { RankingPeriod, periodToPointField } from './types/ranking';

function hasPointField(period: string): boolean {
  return Boolean((periodToPointField as Record<string, unknown>)[period]);
}

Type guard

const PERIOD_POINT_FIELDS = ['pt','weekly_point','monthly_point','quarter_point','yearly_point','global_point'] as const;

function isRankedPeriod(period: string): boolean {
  return (PERIOD_POINT_FIELDS as readonly string[]).length > 0
    && ['daily','weekly','monthly','quarter','yearly','total'].includes(period);
}

Prevention

When it happens

Trigger: A maintainer adds a new RankingPeriod member without adding it to periodToPointField (while remembering periodToOrder/periodToJapanese); direct call to handleIsekaiRanking with an unvalidated type.

Common situations: Enum/map sync drift after extending RankingPeriod; refactor introduces a bypass of parseIsekaiRankingType.

Related errors


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