DIYgod/RSSHub · warning · InvalidParameterError

Not found ${type} in ${id}: ${currentUrl}

Error message

Not found ${type} in ${id}: ${currentUrl}

What it means

The aisixiang thinktank page lists an expert's sections under <h3> headers; the route filters those h3s by exact text match against the requested `type`. If nothing matches it intends to throw InvalidParameterError. IMPORTANT BUG: `$('h3').toArray().filter(...)` always returns an Array, and `!targetList` is therefore always FALSE — so this error is effectively dead code and you will get an empty feed instead. The guard almost never fires.

Source

Thrown at lib/routes/aisixiang/thinktank.ts:47

async function handler(ctx) {
    const { id, type = '' } = ctx.req.param();
    const limit = ctx.req.query('limit') ? Number(ctx.req.query('limit')) : 30;

    const currentUrl = new URL(`thinktank/${id}.html`, rootUrl).href;

    const { data: response } = await got(currentUrl);

    const $ = load(response);

    const title = `${$('h2').first().text()}${type}`;

    let items: any[] = [];

    const targetList = $('h3')
        .toArray()
        .filter((h) => (type ? $(h).text() === type : true));
    if (!targetList) {
        throw new InvalidParameterError(`Not found ${type} in ${id}: ${currentUrl}`);
    }

    for (const l of targetList) {
        items = [...items, ...$(l).parent().find('ul li a').toArray()];
    }

    items = items.slice(0, limit).map((item) => {
        const $item = $(item);

        return {
            title: $item.text().split(':').pop(),
            link: new URL($item.prop('href')!, rootUrl).href,
        };
    });

    return {
        item: await ProcessFeed(limit, items),
        title: `爱思想 - ${title}`,

View on GitHub (pinned to bed535e087)

Solutions

  1. Match the exact <h3> text from the expert's page (watch for full-width punctuation and trailing whitespace).
  2. Omit `type` to receive all sections for the expert.
  3. As a maintainer, fix the dead guard: change `if (!targetList)` to `if (!targetList.length)` so the error actually fires.

Example fix

// before (bug — never throws)
const targetList = $('h3').toArray().filter((h) => (type ? $(h).text() === type : true));
if (!targetList) {
    throw new InvalidParameterError(`Not found ${type} in ${id}: ${currentUrl}`);
}
// after
const targetList = $('h3').toArray().filter((h) => (type ? $(h).text() === type : true));
if (targetList.length === 0) {
    throw new InvalidParameterError(`Not found ${type} in ${id}: ${currentUrl}`);
}
Defensive patterns

Strategy: validation

Validate before calling

// NOTE: the in-route guard is buggy (!targetList on an Array is always false),
// so pre-validate against the actual <h3> texts yourself:
function typeMatchesAnyH3(type, h3Texts) {
  return h3Texts.some((t) => t.trim() === String(type).trim());
}

Type guard

function isKnownThinktankSection(type, sections): boolean {
  return sections.includes(String(type).trim());
}

Try / catch

// Because the route's guard is dead code, you'll get an empty feed, not a throw.
// Validate before calling and treat empty results as the real signal:
const feed = await fetchAisixiang(id, type);
if (feed.items.length === 0 && type) {
  // type didn't match any <h3>; retry without type to get all sections
  return await fetchAisixiang(id, undefined);
}

Prevention

When it happens

Trigger: Calling /aisixiang/thinktank/:id/:type where `type` does not exactly match any <h3> text (whitespace, case, or full-width characters differ). Due to the array-truthiness bug, you get an empty feed rather than this error.

Common situations: Type label copied with trailing spaces; full-width vs half-width chars; expert reorganised their sections; relying on this throw for user-facing validation that never arrives.

Related errors


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