jackwener/OpenCLI · error · CommandExecutionError

无法从 view API 拿到 cid (bvid=${bvid})

Error message

无法从 view API 拿到 cid (bvid=${bvid})

What it means

After a successful view API call, the code extracts a cid — the specific part's content id — either via selectVideoPart (when --page is given) or view.data.cid (default P1). If the resulting cid is falsy it throws this CommandExecutionError, since the player/v2 subtitle API cannot be called without a cid. It indicates the view response had an unexpected shape or the chosen part lacks a cid.

Source

Thrown at clis/bilibili/subtitle.js:39

        const selectedPage = parsePageArg(kwargs.page);
        // 1. 通过 view API 拿 cid。
        //    以前的实现走 page.goto(/video/<bvid>) + window.__INITIAL_STATE__.videoData.cid,
        //    bangumi 绑定的 bvid(番剧/纪录片/电影/综艺)页面 state 不在 videoData 而在 epList,
        //    导致 SELECTOR 错。view API 接受任何 bvid(UGC + PGC 都通),且不依赖 DOM 结构。
        let view;
        try {
            view = await apiGet(page, '/x/web-interface/view', { params: { bvid } });
        }
        catch (err) {
            throw new CommandExecutionError(`获取视频信息失败: ${err?.message || err}`);
        }
        if (view?.code !== 0) {
            throw new CommandExecutionError(`获取视频信息失败: ${view?.message ?? 'unknown'} (${view?.code})`);
        }
        // --page 给定时用该集 cid(selectVideoPart 越界抛错);缺省取整集默认 cid(P1,旧行为)。
        const cid = selectedPage != null ? selectVideoPart(view?.data, selectedPage).cid : view?.data?.cid;
        if (!cid) {
            throw new CommandExecutionError(`无法从 view API 拿到 cid (bvid=${bvid})`);
        }
        // 2. 用带 Wbi 签名的 player/v2 拿字幕列表(之前 evaluate 里 fetch 因为没签名会 403)
        let payload;
        try {
            payload = await apiGet(page, '/x/player/wbi/v2', {
                params: { bvid, cid },
                signed: true,
            });
        }
        catch (err) {
            throw new CommandExecutionError(`获取视频播放信息失败: ${err?.message || err}`);
        }
        if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
            throw new CommandExecutionError('获取到的视频播放信息对象不符合预期格式');
        }
        if (payload.code !== 0) {
            throw new CommandExecutionError(`获取视频播放信息失败: ${payload.message} (${payload.code})`);
        }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Confirm the bvid is a normal UGC video (try omitting --page to use the default P1 cid)
  2. Check the --page value is within range; verify the video actually has that many parts
  3. Open the video in a browser and confirm it plays; if it's a bangumi episode, use the appropriate ep/ss id handling instead
  4. If the API schema changed, update utils.js selectVideoPart / field paths to match current view API responses
Defensive patterns

Strategy: validation

Validate before calling

if (!/^BV[0-9A-Za-z]{10}$/.test(bvid)) throw new Error('invalid bvid format');
// for --page: confirm the part index is plausible
if (pageArg != null && !(Number.isInteger(pageArg) && pageArg >= 1)) throw new Error('bad --page');

Try / catch

try {
  await run(['bilibili', 'subtitle', bvid, '--page', String(n)]);
} catch (e) {
  if (String(e.message).includes('无法从 view API 拿到 cid')) {
    // retry without --page (default P1) or verify the video is a normal UGC video
  } else throw e;
}

Prevention

When it happens

Trigger: view.data.cid missing on a default call; --page N pointing at a part whose cid is undefined; a PGC/bangumi bvid whose view data nests parts differently than expected.

Common situations: Bangumi/PGC content where the standard view payload lacks the expected cid fields; --page out of the parts list producing an object without cid; Bilibili API schema change for certain content types.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/5e5ae152fb14ee6e. Report an issue: GitHub.