jackwener/OpenCLI · error · CommandExecutionError

Bilibili view API returned duplicate page entries for p=${pa

Error message

Bilibili view API returned duplicate page entries for p=${pageNum}

What it means

After filtering pages[] for entries whose page number equals the requested 分P number, selectVideoPart expects exactly one match. More than one entry with the same page number means Bilibili returned inconsistent duplicate data, so the library refuses to guess which cid is correct and fails closed.

Source

Thrown at clis/bilibili/utils.js:132

 * 返回该集 raw 对象(含 cid / part(分集标题) / page / duration)。
 */
export function selectVideoPart(viewData, pageNum) {
    const pages = Array.isArray(viewData?.pages) ? viewData.pages : null;
    if (!pages || pages.length === 0) {
        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();

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-fetch the view API response for that aid/bvid — duplicates are usually server-side data issues that may clear.
  2. Check the video's page list on bilibili.com to confirm the real number of parts.
  3. Inspect the raw response and report/flag the affected video id if duplicates persist.
  4. As a workaround, request a different 分P number or download without --page and pick the part yourself.

Example fix

// before
// duplicate page entries -> throws
const part = selectVideoPart(viewData, pageNum);
// after
const entries = viewData.pages.filter((e) => e.page === pageNum);
const part = entries[0]; // dedupe: take first match intentionally
console.warn(`multiple entries for p=${pageNum}, using first`);
Defensive patterns

Strategy: try-catch

Validate before calling

const dupes = (viewData?.pages ?? []).filter(e => e?.page === pageNum);
if (dupes.length > 1) console.warn(`p=${pageNum} duplicated ${dupes.length}x; picking first`);

Try / catch

try { const part = selectVideoPart(viewData, pageNum); } catch (e) { if (/duplicate page entries/.test(e.message)) { const part = viewData.pages.filter(p => p.page === pageNum)[0]; /* proceed with first */ } else throw e; }

Prevention

When it happens

Trigger: viewData.pages contains two or more entries whose `page` field (validated by readApiPositiveInteger) equals the requested pageNum.

Common situations: Bilibili server-side data corruption on a specific video; duplicated pages[] entries from a buggy cache/proxy; replaying or concatenating captured API responses in tests.

Related errors


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