DIYgod/RSSHub · error · InvalidParameterError

Invalid type: ${type}. Supported types: ${Object.keys(typeMa

Error message

Invalid type: ${type}. Supported types: ${Object.keys(typeMap).join(', ')}

What it means

InvalidParameterError thrown by the Xueqiu stock-info handler when ctx.req.param('type') is not a key of typeMap (all, discuss, trans, news, announcement). The type selects both the search source label and which endpoint (search vs timeline) to call, so an unknown type cannot be defaulted safely.

Source

Thrown at lib/routes/xueqiu/stock-info.ts:53

};

// The two endpoints below correspond to the tabs on the stock page (xueqiu.com/S/:id).
// `source` is the API query value; `label` is the human-readable name shown in the feed title.
// `all` / `discuss` / `trans` are served by the search endpoint; `news` / `announcement`
// are served by the timeline endpoint (the search endpoint ignores these two sources).
const typeMap = {
    all: { source: 'all', label: '全部', endpoint: 'search' },
    discuss: { source: 'user', label: '讨论', endpoint: 'search' },
    trans: { source: 'trans', label: '交易', endpoint: 'search' },
    news: { source: '自选股新闻', label: '资讯', endpoint: 'timeline' },
    announcement: { source: '公告', label: '公告', endpoint: 'timeline' },
};

async function handler(ctx) {
    const id = ctx.req.param('id');
    const type = ctx.req.param('type') || 'announcement';
    if (!Object.hasOwn(typeMap, type)) {
        throw new InvalidParameterError(`Invalid type: ${type}. Supported types: ${Object.keys(typeMap).join(', ')}`);
    }
    const { source, label, endpoint } = typeMap[type];

    const link = `https://xueqiu.com/S/${id}`;
    const cookie = await parseToken(link);

    // Fetch the stock name from the lightweight quote API (the name is rendered
    // client-side on the page, so it cannot be scraped from the static HTML)
    const quoteRes = await got({
        method: 'get',
        url: 'https://stock.xueqiu.com/v5/stock/quote.json',
        searchParams: queryString.stringify({ symbol: id }),
        headers: {
            Cookie: cookie,
            Referer: link,
        },
    });
    const stock_name = quoteRes.data.data?.quote?.name || id;

View on GitHub (pinned to bed535e087)

Solutions

  1. Use one of: all, discuss, trans, news, announcement.
  2. If you want the default, omit the type segment (the handler defaults to 'announcement').
  3. Add new types to typeMap if Xueqiu exposes a new feed.
Defensive patterns

Strategy: validation

Validate before calling

const TYPE_KEYS = new Set(Object.keys(typeMap));
function resolveType(raw: string | undefined) {
    const type = raw || 'announcement';
    if (!TYPE_KEYS.has(type)) {
        throw new InvalidParameterError(`Invalid type "${type}". Supported: ${[...TYPE_KEYS].join(', ')}`);
    }
    return type as keyof typeof typeMap;
}

Type guard

function isStockInfoType(value: string): value is keyof typeof typeMap {
    return Object.hasOwn(typeMap, value);
}

Prevention

When it happens

Trigger: A request to /xueqiu/stock-info/:id/:type where type is outside the five keys, e.g. /xueqiu/stock-info/SH600519/comment or omitting it in a path that still passes a third segment. Validated before any Xueqiu call.

Common situations: Caller used a type name from another Xueqiu route; typo; integrator expected 'comments' instead of 'discuss'.

Related errors


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