{"record":{"id":"47a40bbeedd49939","repo":"jackwener/OpenCLI","slug":"p-error-message-error","errorCode":null,"errorMessage":"获取视频分P信息失败: ${error?.message || error}","messagePattern":"获取视频分P信息失败: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/bilibili/download.js","lineNumber":88,"sourceCode":"        catch {\n            // nav 查询失败按\"无会员\"保守处理，走下面的拦截\n        }\n    }\n    throw new CliError(\n        'PAID_CONTENT',\n        `该视频为付费内容（${PAYMENT_LABELS[paymentType]}），当前账号无观看权益，无法获取完整视频流`,\n        '若已购买/已充电/已开通会员，加 --force 跳过本检查直接下载',\n        EXIT_CODES.NOPERM,\n    );\n}\n\nasync function loadSelectedPart(page, bvid, pageNum) {\n    let payload;\n    try {\n        payload = await apiGet(page, '/x/web-interface/view', { params: { bvid } });\n    }\n    catch (error) {\n        throw new CommandExecutionError(`获取视频分P信息失败: ${error?.message || error}`);\n    }\n    if (!isObject(payload) || payload.code !== 0) {\n        throw new CommandExecutionError(`获取视频分P信息失败: ${payload?.message ?? 'unknown'} (${payload?.code ?? 'malformed'})`);\n    }\n    return selectVideoPart(payload.data, pageNum);\n}\n\ncli({\n    site: 'bilibili',\n    name: 'download',\n    access: 'read',\n    description: '下载B站视频（需要 yt-dlp）',\n    domain: 'www.bilibili.com',\n    strategy: Strategy.COOKIE,\n    args: [\n        { name: 'bvid', required: true, positional: true, help: 'Video BV ID (e.g., BV1xxx)' },\n        { name: 'output', default: './bilibili-downloads', help: 'Output directory' },\n        { name: 'quality', default: 'best', help: 'Video quality (best, 1080p, 720p, 480p)' },","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/bilibili/download.js#L70-L106","documentation":"loadSelectedPart wraps the /x/web-interface/view call used to resolve the requested 分P (part) number. If the transport/API call throws (network, timeout, HTTP error) or the response envelope is malformed/non-zero code, it is converted into a Chinese-language CommandExecutionError prefixed 获取视频分P信息失败 with the underlying reason appended.","triggerScenarios":"Using --page on a multi-P video while /x/web-interface/view fails: network timeout/DNS failure, Bilibili returning code != 0 (e.g. -404 video not found, -352 risk control, -403), rate limiting, or invalid cookie session.","commonSituations":"Typo in bvid or URL resolving to a removed video; triggering anti-bot risk control (-352) after many requests; expired cookies; offline/proxy network issues; --page given for a video whose data can't be fetched.","solutions":["Retry after a short wait if it was a timeout or risk-control blip (-352); reduce request frequency.","Verify the bvid/URL is correct and the video still exists (code -404 means deleted/invalid).","Refresh Bilibili cookies / re-login if auth-related codes appear.","Check network connectivity and proxy/VPN configuration before retrying."],"exampleFix":"// caller-side retry around the CLI-level failure\ntry {\n    await download(bvid, { page: 2 });\n} catch (e) {\n    if (String(e.message).startsWith('获取视频分P信息失败')) {\n        await new Promise(r => setTimeout(r, 2000));\n        await download(bvid, { page: 2 }); // retry once\n    }\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    await download(bvid, { page: n });\n} catch (e) {\n    if (/获取视频分P信息失败/.test(e.message)) {\n        if (/-404/.test(e.message)) { /* video gone: don't retry */ }\n        else { /* transient (timeout/-352): wait and retry with backoff */ }\n    } else throw e;\n}","preventionTips":["Validate bvid/URL and that the video still exists before batch downloads","Throttle request rate to avoid -352 risk-control rejections","Refresh cookies when auth-related failure codes appear","Verify network/proxy connectivity before large download runs"],"tags":["bilibili","network","api","video-metadata"],"backgroundTag":"api-request-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}