jackwener/OpenCLI · error · CommandExecutionError

Bilibili view API returned a malformed ${label}

Error message

Bilibili view API returned a malformed ${label}

What it means

readApiPositiveInteger validates that a numeric field from the Bilibili view API (e.g. page, cid) is a positive integer — either a number or a numeric string matching /^[1-9]\d*$/. If the value is missing, zero, negative, fractional, non-numeric, or an unsafe integer, the library fails closed because page/cid are the source-of-truth for selecting a video part and using a malformed one would target the wrong resource.

Source

Thrown at clis/bilibili/utils.js:108

    if (typeof value !== 'string' || !/^[1-9]\d*$/.test(value)) {
        throw new ArgumentError(`--page must be a positive decimal integer, got: ${String(value)}`);
    }
    const n = Number(value);
    if (!Number.isSafeInteger(n)) {
        throw new ArgumentError(`--page is too large: ${value}`);
    }
    return n;
}

function readApiPositiveInteger(value, label) {
    if (typeof value === 'number' && Number.isSafeInteger(value) && value >= 1) {
        return value;
    }
    if (typeof value === 'string' && /^[1-9]\d*$/.test(value)) {
        const n = Number(value);
        if (Number.isSafeInteger(n)) return n;
    }
    throw new CommandExecutionError(`Bilibili view API returned a malformed ${label}`);
}

/**
 * 从 view API 的 data.pages 数组取第 N 集(1-based)。
 * page/cid 都以 view API 的 pages[] 为 source-of-truth;缺失、重复或畸形都 fail closed。
 * 返回该集 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');

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-fetch the view API response — the malformed value is often transient (CDN/cache glitch).
  2. Verify the video actually has multi-page data (check data.pages exists and each entry has page/cid).
  3. Log the full raw response body to see which field and value failed validation.
  4. If Bilibili changed the schema, update the validation/field extraction in clis/bilibili/utils.js accordingly.

Example fix

// before
const part = viewData.pages[0];
const cid = part.cid; // may be undefined -> CommandExecutionError
// after
if (typeof part?.cid === 'number' && Number.isSafeInteger(part.cid) && part.cid > 0) {
  const cid = part.cid;
}
Defensive patterns

Strategy: validation

Validate before calling

function isValidPart(p){ return p && typeof p==='object' && Number.isSafeInteger(p.page) && p.page>0 && Number.isSafeInteger(p.cid) && p.cid>0; }
const usable = (viewData?.pages ?? []).filter(isValidPart);

Type guard

function isPositiveInteger(v){ return (typeof v==='number' || (typeof v==='string' && /^[1-9]\d*$/.test(v))) && Number.isSafeInteger(Number(v)) && Number(v)>0; }

Try / catch

try { const part = selectVideoPart(viewData, pageNum); } catch (e) { if (/malformed/.test(e.message)) { viewData = await refetchViewData(url); /* retry once */ } else throw e; }

Prevention

When it happens

Trigger: Bilibili's /x/web-interface/view endpoint returns a pages[] entry (or another validated field) whose `page` or `cid` is undefined, null, 0, a float, a negative number, a non-numeric string, or a number beyond Number.MAX_SAFE_INTEGER.

Common situations: Bilibili API schema changes or partial responses during incidents; caching proxies/CDNs returning truncated JSON; mocked or replayed responses missing fields; an API regression returning null cid for newly uploaded videos.

Understand the failure class

Related errors


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