DIYgod/RSSHub · error · Error
Got error code ${data.code} while fetching: ${data.message}
Error message
Got error code ${data.code} while fetching: ${data.message} What it means
Thrown by the bilibili/video API path (fetchVideoListFromApi) when the wbi-signed GET to https://api.bilibili.com/x/space/wbi/arc/search returns a non-zero business code. The handler logs the full data payload at error level, then re-throws the upstream code and message. This is the primary failure mode for the user-video feed and is what triggers the browser-mode fallback in getVideoList().
Source
Thrown at lib/routes/bilibili/video.ts:168
const dmImgList = utils.getDmImgList();
const dmImgInter = utils.getDmImgInter();
const renderData = await cache.getRenderData(uid);
const params = utils.addWbiVerifyInfo(
utils.addRenderData(utils.addDmVerifyInfoWithInter(`mid=${uid}&ps=30&tid=0&pn=1&keyword=&order=pubdate&platform=web&web_location=1550101&order_avoided=true`, dmImgList, dmImgInter), renderData),
wbiVerifyString
);
const response = await got(`https://api.bilibili.com${videoListApiPath}?${params}`, {
headers: {
Referer: `https://space.bilibili.com/${uid}`,
origin: 'https://space.bilibili.com',
Cookie: cookie,
},
});
const data = response.data;
if (data.code) {
logger.error(JSON.stringify(data.data));
throw new Error(`Got error code ${data.code} while fetching: ${data.message}`);
}
return data.data;
}
async function fetchVideoListFromBrowser(uid: string): Promise<VideoListData> {
const cookie = cache.getConfiguredCookie();
const videoUrl = `https://space.bilibili.com/${uid}/video`;
logger.info(`[bilibili/video] fetching via playwright: ${videoUrl}`);
const { destroy, page } = await getPlaywrightPage(videoUrl, {
closeTimeout: browserCloseTimeout,
noGoto: true,
onBeforeLoad: async (page) => {
if (cookie) {
await applyCookie(page, cookie);
}
View on GitHub (pinned to bed535e087)
Solutions
- Set BILIBILI_COOKIE_* so cache.getCookie() returns a valid session and the request is authenticated.
- Verify the uid exists (open https://space.bilibili.com/{uid}/video in a browser).
- Clear the wbi verify cache key (cache.getWbiVerifyString) so the signature keys refresh; ensure buvid is being fetched.
- Decode the code: -101 cookie invalid, -352/-479 risk control (slow down, rotate IP), -400 bad request (check uid).
- Note the route already falls back to browser mode on this error — if that also fails you'll see error 119/116/117.
Example fix
// before
if (data.code) {
logger.error(JSON.stringify(data.data));
throw new Error(`Got error code ${data.code} while fetching: ${data.message}`);
}
// after (map common codes to actionable hints)
if (data.code) {
logger.error(`[bilibili/video] api code ${data.code}: ${JSON.stringify(data.data)}`);
if (data.code === -101) {
throw new ConfigNotFoundError(`Bilibili cookie missing/invalid for uid ${uid} (code -101)`);
}
throw new Error(`Got error code ${data.code} while fetching: ${data.message ?? 'no message'}`);
} Defensive patterns
Strategy: retry
Validate before calling
// Health-check the wbi-signed video API for a uid before relying on it.
import ofetch from '@/utils/ofetch';
async function videoApiOk(uid: string, signedQuery: string) {
const r = await ofetch<{ code: number }>(`https://api.bilibili.com/x/space/wbi/arc/search?${signedQuery}`, {
headers: { Referer: `https://space.bilibili.com/${uid}` },
});
return r.code === 0;
} Type guard
interface VideoListResponse { code?: number; data?: VideoListData; message?: string }
function isVideoListOk(r: VideoListResponse): r is { code: 0; data: VideoListData } {
return r.code === 0 && !!r.data;
} Try / catch
try {
if (data.code) throw new Error(`code ${data.code}: ${data.message}`);
} catch (e) {
const m = e instanceof Error ? e.message : '';
if (m.includes('-101')) throw new Error(`Set or refresh BILIBILI_COOKIE_* (session invalid)`);
if (m.includes('-352') || m.includes('-479') || m.includes('-799')) {
// risk control — the route already falls back to browser mode; if that also fails, backoff
await backoffRetry();
}
throw e;
} Prevention
- Configure BILIBILI_COOKIE_* so cache.getCookie() authenticates the request.
- Keep wbi keys fresh — invalidate the cache entry behind cache.getWbiVerifyString when -352/-479 appear.
- Ensure buvid / dm_img state is being fetched and appended by utils.addDmVerifyInfoWithInter; missing buvid triggers risk control.
- Cache the video list for several minutes so transient -352s don't cause repeated full API calls.
When it happens
Trigger: GET /bilibili/user/video/:uid where the wbi/arc/search API answers code !== 0 — most often -352/-479 (risk control / anti-crawler, frequently because the wbi signature is stale or missing buvid/cookie), -101 (not logged in), or -400 (request invalid, e.g. bad uid).
Common situations: No BILIBILI_COOKIE_* configured and the public wbi signature was rejected; wbi keys (cache.getWbiVerifyString) stale; RSSHub IP flagged; uid invalid or deleted; buvid/dm_img missing in the signed params.
Related errors
- response.message ?? `Error code ${response.code}`
- response.message ?? `Error code ${response.code}`
- response.message ?? response.msg ?? `Error code ${response.c
- response.message ?? response.msg ?? `Error code ${response.c
- msgUnread.message ?? `Error code ${msgUnread.code}`
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/893b67fbb4556d13.
Report an issue: GitHub.