{"record":{"id":"836ded671f5a2455","repo":"jackwener/OpenCLI","slug":"view-message-unknown-view-c","errorCode":null,"errorMessage":"获取视频信息失败: ${view?.message ?? 'unknown'} (${view?.code})","messagePattern":"获取视频信息失败: (.+?) \\((.+?)\\)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/bilibili/subtitle.js","lineNumber":34,"sourceCode":"    columns: ['index', 'from', 'to', 'content'],\n    func: async (page, kwargs) => {\n        if (!page)\n            throw new CommandExecutionError('Browser session required for bilibili subtitle');\n        const bvid = await resolveBvid(kwargs.bvid);\n        const selectedPage = parsePageArg(kwargs.page);\n        // 1. 通过 view API 拿 cid。\n        //    以前的实现走 page.goto(/video/<bvid>) + window.__INITIAL_STATE__.videoData.cid，\n        //    bangumi 绑定的 bvid（番剧/纪录片/电影/综艺）页面 state 不在 videoData 而在 epList，\n        //    导致 SELECTOR 错。view API 接受任何 bvid（UGC + PGC 都通），且不依赖 DOM 结构。\n        let view;\n        try {\n            view = await apiGet(page, '/x/web-interface/view', { params: { bvid } });\n        }\n        catch (err) {\n            throw new CommandExecutionError(`获取视频信息失败: ${err?.message || err}`);\n        }\n        if (view?.code !== 0) {\n            throw new CommandExecutionError(`获取视频信息失败: ${view?.message ?? 'unknown'} (${view?.code})`);\n        }\n        // --page 给定时用该集 cid（selectVideoPart 越界抛错）；缺省取整集默认 cid（P1，旧行为）。\n        const cid = selectedPage != null ? selectVideoPart(view?.data, selectedPage).cid : view?.data?.cid;\n        if (!cid) {\n            throw new CommandExecutionError(`无法从 view API 拿到 cid (bvid=${bvid})`);\n        }\n        // 2. 用带 Wbi 签名的 player/v2 拿字幕列表（之前 evaluate 里 fetch 因为没签名会 403）\n        let payload;\n        try {\n            payload = await apiGet(page, '/x/player/wbi/v2', {\n                params: { bvid, cid },\n                signed: true,\n            });\n        }\n        catch (err) {\n            throw new CommandExecutionError(`获取视频播放信息失败: ${err?.message || err}`);\n        }\n        if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/bilibili/subtitle.js#L16-L52","documentation":"The Bilibili view API responded successfully but with a non-zero code field, meaning the API itself rejected the request (e.g. -400 request error, -404 not found, -412 risk control). The error surfaces the API's own message and numeric code. This is the library's way of turning Bilibili business-level failures into a thrown CommandExecutionError.","triggerScenarios":"view?.code !== 0 after apiGet('/x/web-interface/view') — typically a malformed/nonexistent bvid, deleted/private video, or Bilibili risk-control (-412) rejection of the request.","commonSituations":"Typo in the BV id; video removed or set to private; b23.tv short link resolving to a bangumi page with odd handling; too many requests triggering -412 anti-crawler; unlogged/risk-controlled account.","solutions":["Decode the code in the message: -400 bad request → check bvid format; -404 → video doesn't exist/was deleted; -412 → risk control, slow down or log in","Verify the bvid exists by opening https://www.bilibili.com/video/<bvid> in a browser","Retry later or from a logged-in session if you got -412 (anti-bot/risk control)","If using a URL/short link, confirm it resolves to the intended UGC video bvid"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-check the bvid exists\nconst res = await fetch(`https://api.bilibili.com/x/web-interface/view?bvid=${bvid}`);\nconst j = await res.json();\nif (j.code !== 0) throw new Error(`bvid ${bvid} rejected by view API: ${j.message} (${j.code})`);","typeGuard":null,"tryCatchPattern":"try {\n  await run(['bilibili', 'subtitle', bvid]);\n} catch (e) {\n  const m = /获取视频信息失败: (.+) \\((-?\\d+)\\)/.exec(String(e.message));\n  if (m) {\n    const [, msg, code] = m;\n    if (code === '-412' || code === '-352') { /* back off, use logged-in session */ }\n    else if (code === '-404' || code === '-400') { /* fix/validate bvid */ }\n  } else throw e;\n}","preventionTips":["Validate BV ids before use (regex /^BV[0-9A-Za-z]{10}$/)","Don't hammer the API — add delays to avoid -412 risk control","Check video availability manually before batch processing"],"tags":["api","bilibili","risk-control","business-error"],"backgroundTag":"api-error-code","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}