{"record":{"id":"893b67fbb4556d13","repo":"DIYgod/RSSHub","slug":"got-error-code-data-code-while-fetching-data-893b67","errorCode":null,"errorMessage":"Got error code ${data.code} while fetching: ${data.message}","messagePattern":"Got error code (.+?) while fetching: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/bilibili/video.ts","lineNumber":168,"sourceCode":"    const dmImgList = utils.getDmImgList();\n    const dmImgInter = utils.getDmImgInter();\n    const renderData = await cache.getRenderData(uid);\n\n    const params = utils.addWbiVerifyInfo(\n        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),\n        wbiVerifyString\n    );\n    const response = await got(`https://api.bilibili.com${videoListApiPath}?${params}`, {\n        headers: {\n            Referer: `https://space.bilibili.com/${uid}`,\n            origin: 'https://space.bilibili.com',\n            Cookie: cookie,\n        },\n    });\n    const data = response.data;\n    if (data.code) {\n        logger.error(JSON.stringify(data.data));\n        throw new Error(`Got error code ${data.code} while fetching: ${data.message}`);\n    }\n\n    return data.data;\n}\n\nasync function fetchVideoListFromBrowser(uid: string): Promise<VideoListData> {\n    const cookie = cache.getConfiguredCookie();\n    const videoUrl = `https://space.bilibili.com/${uid}/video`;\n    logger.info(`[bilibili/video] fetching via playwright: ${videoUrl}`);\n\n    const { destroy, page } = await getPlaywrightPage(videoUrl, {\n        closeTimeout: browserCloseTimeout,\n        noGoto: true,\n        onBeforeLoad: async (page) => {\n            if (cookie) {\n                await applyCookie(page, cookie);\n            }\n","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/bilibili/video.ts#L150-L186","documentation":"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().","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nif (data.code) {\n    logger.error(JSON.stringify(data.data));\n    throw new Error(`Got error code ${data.code} while fetching: ${data.message}`);\n}\n\n// after (map common codes to actionable hints)\nif (data.code) {\n    logger.error(`[bilibili/video] api code ${data.code}: ${JSON.stringify(data.data)}`);\n    if (data.code === -101) {\n        throw new ConfigNotFoundError(`Bilibili cookie missing/invalid for uid ${uid} (code -101)`);\n    }\n    throw new Error(`Got error code ${data.code} while fetching: ${data.message ?? 'no message'}`);\n}","handlingStrategy":"retry","validationCode":"// Health-check the wbi-signed video API for a uid before relying on it.\nimport ofetch from '@/utils/ofetch';\nasync function videoApiOk(uid: string, signedQuery: string) {\n  const r = await ofetch<{ code: number }>(`https://api.bilibili.com/x/space/wbi/arc/search?${signedQuery}`, {\n    headers: { Referer: `https://space.bilibili.com/${uid}` },\n  });\n  return r.code === 0;\n}","typeGuard":"interface VideoListResponse { code?: number; data?: VideoListData; message?: string }\nfunction isVideoListOk(r: VideoListResponse): r is { code: 0; data: VideoListData } {\n  return r.code === 0 && !!r.data;\n}","tryCatchPattern":"try {\n  if (data.code) throw new Error(`code ${data.code}: ${data.message}`);\n} catch (e) {\n  const m = e instanceof Error ? e.message : '';\n  if (m.includes('-101')) throw new Error(`Set or refresh BILIBILI_COOKIE_* (session invalid)`);\n  if (m.includes('-352') || m.includes('-479') || m.includes('-799')) {\n    // risk control — the route already falls back to browser mode; if that also fails, backoff\n    await backoffRetry();\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["bilibili","api-error","authentication","anti-crawler","wbi","rsshub"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}