jackwener/OpenCLI · error · CliError

PAID_CONTENT

PAID_CONTENT

Error message

该视频为付费内容(${PAYMENT_LABELS[paymentType]}),当前账号无观看权益,无法获取完整视频流

What it means

The paid-content pre-check determined the video requires payment the current account lacks: rights.pay (VIP-exclusive/OGV), ugc_pay/arc_pay (per-purchase), or is_upower_exclusive (charging-exclusive). For VIP content it also checked the nav API — a non-VIP account proceeds to interception. This structured CliError (code PAID_CONTENT, exit 77) avoids yt-dlp failing mid-download with an unhelpful stderr dump. Users who already bought/recharged/subscribed can bypass with --force.

Source

Thrown at clis/bilibili/download.js:74

        ? 'vip'
        : (rights.ugc_pay || rights.arc_pay)
            ? 'ugc_pay'
            : d.is_upower_exclusive
                ? 'upower'
                : '';
    if (!paymentType)
        return;
    if (paymentType === 'vip') {
        try {
            const nav = await apiGet(page, '/x/web-interface/nav');
            if (nav.code === 0 && Number(nav.data?.vipStatus) === 1)
                return;
        }
        catch {
            // nav 查询失败按"无会员"保守处理,走下面的拦截
        }
    }
    throw new CliError(
        'PAID_CONTENT',
        `该视频为付费内容(${PAYMENT_LABELS[paymentType]}),当前账号无观看权益,无法获取完整视频流`,
        '若已购买/已充电/已开通会员,加 --force 跳过本检查直接下载',
        EXIT_CODES.NOPERM,
    );
}

async function loadSelectedPart(page, bvid, pageNum) {
    let payload;
    try {
        payload = await apiGet(page, '/x/web-interface/view', { params: { bvid } });
    }
    catch (error) {
        throw new CommandExecutionError(`获取视频分P信息失败: ${error?.message || error}`);
    }
    if (!isObject(payload) || payload.code !== 0) {
        throw new CommandExecutionError(`获取视频分P信息失败: ${payload?.message ?? 'unknown'} (${payload?.code ?? 'malformed'})`);
    }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. If you have the entitlement, re-login/refresh cookies so the session reflects your purchase or VIP status, then retry.
  2. Add --force to the download command to skip the paid-content pre-check and let yt-dlp use your entitlement.
  3. Upgrade to Bilibili大会员 if the content is VIP-exclusive and you want full-stream access.
  4. Choose a different, non-paid video if you don't hold entitlement.
Defensive patterns

Strategy: try-catch

Validate before calling

const v = await (await fetch(viewApiUrl, { headers: { cookie } })).json();
const r = v?.data?.rights ?? {};
const paid = Boolean(r.pay || r.ugc_pay || r.arc_pay) || Boolean(v?.data?.is_upower_exclusive);
if (paid) { /* check entitlement or plan --force */ }

Type guard

function paymentType(data) {
    const r = data?.rights ?? {};
    if (r.pay) return 'vip';
    if (r.ugc_pay || r.arc_pay) return 'ugc_pay';
    if (data?.is_upower_exclusive) return 'upower';
    return null;
}

Try / catch

try {
    await download(bvid);
} catch (e) {
    if (e.code === 'PAID_CONTENT') {
        // re-run with --force if you own the content, or pick another video
    } else throw e;
}

Prevention

When it happens

Trigger: Downloading a video whose rights flag marks it vip / ugc_pay / arc_pay / upower-exclusive while the logged-in account has no matching entitlement (vip flag with nav showing vipStatus != 1, or ugc_pay/upower with no cheap entitlement check so always intercepted).

Common situations: Trying to download a大会员-only anime/OGV with a free account; a charging-exclusive video you haven't recharged; a purchased UGC single-pay video where the purchase isn't reflected to this cookie session; valid VIP but cookies expired so nav reports non-VIP.

Related errors


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