jackwener/OpenCLI · error · CommandExecutionError

分P 序号超出范围:p=${pageNum}(该视频共 ${total} 集)

Error message

分P 序号超出范围:p=${pageNum}(该视频共 ${total} 集)

What it means

No entry in pages[] matched the requested 分P number, so the requested part does not exist for this video. The error reports the requested p=N and the total number of parts (pages length, falling back to viewData.videos, then 1) so the caller can pick a valid range.

Source

Thrown at clis/bilibili/utils.js:137

        throw new CommandExecutionError('Bilibili view API did not return pages[] for --page selection');
    }
    const matches = [];
    for (const entry of pages) {
        if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
            throw new CommandExecutionError('Bilibili view API returned a malformed pages[] entry');
        }
        const apiPage = readApiPositiveInteger(entry.page, 'page number');
        if (apiPage === pageNum) {
            matches.push(entry);
        }
    }
    if (matches.length > 1) {
        throw new CommandExecutionError(`Bilibili view API returned duplicate page entries for p=${pageNum}`);
    }
    const part = matches[0];
    if (!part) {
        const total = pages.length || viewData?.videos || 1;
        throw new CommandExecutionError(`分P 序号超出范围:p=${pageNum}(该视频共 ${total} 集)`);
    }
    readApiPositiveInteger(part.cid, `cid for p=${pageNum}`);
    return part;
}

const MIXIN_KEY_ENC_TAB = [
    46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
    33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
    61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
    36, 20, 34, 44, 52,
];
export function stripHtml(s) {
    return s.replace(/<[^>]+>/g, '').replace(/&[a-z]+;/gi, ' ').trim();
}
export function payloadData(payload) {
    return payload?.data ?? payload;
}
async function getNavData(page) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Use a 分P number between 1 and the total number of parts shown in the error message (1-based).
  2. Re-fetch the view API and print pages[].page to see valid part numbers before selecting.
  3. Remove the --page flag to download the default (first) part.
  4. If the video changed, update your saved page index — part numbering can shift after edits.

Example fix

// before
await cmd(['bili', 'download', url, '--page', '5']); // video only has 3 parts
// after
const view = await getViewData(url);
const total = view.pages?.length ?? 1;
const page = Math.min(5, total);
await cmd(['bili', 'download', url, '--page', String(page)]);
Defensive patterns

Strategy: validation

Validate before calling

const total = Array.isArray(viewData?.pages) ? viewData.pages.length : 1;
if (!Number.isInteger(pageNum) || pageNum < 1 || pageNum > total) throw new RangeError(`--page must be 1..${total} (1-based)`);

Try / catch

try { const part = selectVideoPart(viewData, pageNum); } catch (e) { if (/序号超出范围/.test(e.message)) { console.error(e.message); /* parse total from message and clamp */ } else throw e; }

Prevention

When it happens

Trigger: Calling selectVideoPart(viewData, pageNum) (or passing --page N) where N is greater than the number of pages, less than 1, or the video's pages[] simply has no entry with that page number.

Common situations: Hardcoding --page 2 for a single-part video; the video was re-uploaded/edited and now has fewer parts; off-by-one confusion (分P numbers are 1-based); a playlist index reused across different videos.

Related errors


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