jackwener/OpenCLI · error · CommandExecutionError

Bilibili ${label} API failed: ${message} (${payload.code})

Error message

Bilibili ${label} API failed: ${message} (${payload.code})

What it means

The Bilibili API returned valid JSON with a non-zero `code` that was NOT auth-like, so the library surfaces the API's own message and code as a CommandExecutionError. This is the generic 'API said no' path — the server processed the request but rejected it for a business reason.

Source

Thrown at clis/bilibili/utils.js:235

 * `code` carries either an auth/permission failure (login expired, CSRF rejected,
 * forbidden) or an application-level error (rate limit, validation, etc.). These
 * two helpers route the envelope to the right typed error so every write adapter
 * surfaces login problems as `AuthRequiredError`, not a generic execution error.
 */
export function isAuthLikeBilibiliError(code, message) {
    return code === -101 || code === -111 || code === -403 || /csrf|登录|账号|权限|forbidden|permission|login/i.test(String(message ?? ''));
}

export function requireOkPayload(payload, label) {
    if (!payload || typeof payload !== 'object' || Array.isArray(payload) || !Object.hasOwn(payload, 'code')) {
        throw new CommandExecutionError(`Bilibili ${label} API returned a malformed payload`);
    }
    if (payload.code !== 0) {
        const message = payload.message ?? 'unknown error';
        if (isAuthLikeBilibiliError(payload.code, message)) {
            throw new AuthRequiredError('bilibili.com', `Bilibili ${label} API requires login or permission: ${message} (${payload.code})`);
        }
        throw new CommandExecutionError(`Bilibili ${label} API failed: ${message} (${payload.code})`);
    }
    return payload.data;
}

/**
 * POST form-encoded params to a Bilibili API endpoint.
 * Runs inside the logged-in browser context and auto-attaches the bili_jct CSRF token,
 * which Bilibili requires on every authenticated write request.
 */
export async function apiPost(page, path, opts = {}) {
    const params = opts.params ?? {};
    const stringified = Object.fromEntries(Object.entries(params).map(([k, v]) => [k, String(v)]));
    const paramsJs = JSON.stringify(stringified);
    const urlJs = JSON.stringify(`https://api.bilibili.com${path}`);
    return page.evaluate(`
    async () => {
      const csrf = (document.cookie.match(/bili_jct=([^;]+)/) || [])[1] || "";
      const body = new URLSearchParams(${paramsJs});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read the code/message in the error — Bilibili's codes are documented (e.g., -404 not found, 62002 hidden video) and indicate the exact problem.
  2. Verify the aid/bvid/params you passed are correct and the video still exists and is public.
  3. If you get risk-control codes (-509/-412), slow request rate, use cookies, or a residential IP.
  4. Retry with backoff only for transient codes; do not retry permanent codes like -400/-404.

Example fix

// before
try { await download(url); }
catch (e) { retry(url); } // retries even for -404
// after
try { await download(url); }
catch (e) {
  if (!/-40[04]|62002/.test(e.message)) retry(url);
  else console.error('Permanent API rejection:', e.message);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight: check the video is public and exists
const v = await (await fetch(`https://api.bilibili.com/x/web-interface/view?bvid=${bvid}`)).json();
if (v.code === -404 || v.code === 62002) throw new Error(`Video unavailable: ${v.message}`);

Try / catch

try { const data = requireOkPayload(payload, 'view'); } catch (e) { const m = /\((-[0-9]+)\)$/.exec(e.message); if (m && ['-400','-404','62002'].includes(m[1])) { /* permanent: don't retry */ } else if (m && ['-509','-412'].includes(m[1])) { await backoffAndRetry(); } else throw e; }

Prevention

When it happens

Trigger: payload.code !== 0 with codes like -400 (bad request), -404 (not found), 62002 (video invisible/hidden), -509 (risk control), 62012 (comments closed), etc., and the message doesn't match the auth regex.

Common situations: Malformed aid/bvid parameters; deleted or made-private videos; Bilibili risk-controlling datacenter IPs; passing wrong params to a specific endpoint (e.g., wrong search_type); region-locked content.

Related errors


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