DIYgod/RSSHub · error

response.message

Error message

response.message

What it means

Thrown by the ranking handler when the GET to `${apiBase}?${apiParams}` (e.g. https://api.bilibili.com/x/web-interface/ranking/v2) returns HTTP 200 with a non-zero business code. Unlike other bilibili routes it propagates `response.message` directly with no fallback, so if the upstream omits the field the thrown Error will have an empty/undefined message. A non-zero code typically means Bilibili rejected the request (risk control, web_location signature issue, or region restriction).

Source

Thrown at lib/routes/bilibili/ranking.ts:254

    const rid = ctx.req.param('rid') || 'all';
    const embed = !ctx.req.param('embed');
    const isNumericRid = /^\d+$/.test(rid);

    const { apiBase, apiParams, referer, ridChinese, link, ridType } = getAPI(isNumericRid, rid);
    if (ridType.startsWith('pgc/')) {
        throw new Error('This type of ranking is not supported yet');
    }

    const response = await ofetch(`${apiBase}?${apiParams}`, {
        headers: {
            Referer: referer,
            origin: 'https://www.bilibili.com',
        },
    });

    if (response.code !== 0) {
        throw new Error(response.message);
    }
    const data = response.data || response.result;
    const list = data.list || [];
    return {
        title: `bilibili 排行榜-${ridChinese}`,
        link,
        item: await Promise.all(
            list.map(async (item) => {
                const subtitles = isJsonFeed && !config.bilibili.excludeSubtitles && item.bvid ? await cache.getVideoSubtitleAttachment(item.bvid) : [];
                return {
                    title: item.title,
                    description: utils.renderUGCDescription(embed, item.pic, item.desc || item.title, item.aid, undefined, item.bvid),
                    pubDate: item.ctime && parseDate(item.ctime, 'X'),
                    author: item.owner.name,
                    link: !item.ctime || (item.ctime > utils.bvidTime && item.bvid) ? `https://www.bilibili.com/video/${item.bvid}` : `https://www.bilibili.com/video/av${item.aid}`,
                    image: item.pic,
                    attachments: item.bvid
                        ? [

View on GitHub (pinned to bed535e087)

Solutions

  1. Retry after a short cooldown — many -352/-479 responses are transient rate-limit signals.
  2. If you self-host, route RSSHub through a residential/cleaner IP or add the wbi signature (w_rid, wts) to apiParams as the comments at the top of ranking.ts already imply is required.
  3. Reduce polling frequency and avoid concurrent requests to the same ranking endpoint.
  4. If response.message is empty, patch the throw to include the code: `throw new Error(response.message || 'Error code ' + response.code)`.

Example fix

// before
if (response.code !== 0) {
    throw new Error(response.message);
}

// after (guarantee a non-empty, actionable message)
if (response.code !== 0) {
    throw new Error(response.message || `Bilibili ranking API error: code ${response.code}`);
}
Defensive patterns

Strategy: retry

Validate before calling

// Soft pre-flight: probe the ranking endpoint and surface risk-control early.
import ofetch from '@/utils/ofetch';
async function rankingReachable(apiBase: string, apiParams: string) {
  try {
    const r = await ofetch<{ code: number }>(`${apiBase}?${apiParams}`, { headers: { Referer: 'https://www.bilibili.com/' } });
    return r.code === 0;
  } catch { return false; }
}

Type guard

interface RankEnv<T> { code: number; message?: string; data?: T; result?: T }
function isRankOk<T>(r: RankEnv<T>): r is RankEnv<T> & { code: 0 } { return r.code === 0; }

Try / catch

try {
  if (response.code !== 0) throw new Error(response.message);
} catch (e) {
  const m = (e instanceof Error ? e.message : '') || '';
  if (m.includes('-352') || m.includes('-479') || m.includes('-799')) {
    // transient anti-crawler — retry with backoff
    await backoffRetry(() => ofetch(`${apiBase}?${apiParams}`, opts));
  }
  throw e;
}

Prevention

When it happens

Trigger: GET /bilibili/ranking/:rid where the ranking/v2 endpoint answers code !== 0 — commonly -352/-799 (risk control / anti-crawler) when RSSHub is rate-limited or missing the w_rid/wts wbi signature, or -479 (恶意请求) on aggressive polling.

Common situations: Public RSSHub instance IP flagged by Bilibili's anti-crawler; missing/rotated wbi signing keys; the ranking endpoint now requires a w_rid/wts pair not appended here; transient upstream error.

Related errors


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