jackwener/OpenCLI · error · CommandExecutionError

字幕获取失败: ${items.error}${items.text ? ' — ' + items.text : ''

Error message

字幕获取失败: ${items.error}${items.text ? ' — ' + items.text : ''}

What it means

A CommandExecutionError thrown when the in-page fetch script completes but reports an error via its result object (items.error), e.g. the CDN returned a non-OK HTTP status or the JSON body could not be parsed. The error text and optional accompanying text from the page script are included in the message.

Source

Thrown at clis/bilibili/subtitle.js:114

             const subJson = JSON.parse(text);
             // B站真实返回格式是 { font_size: 0.4, font_color: "#FFFFFF", background_alpha: 0.5, background_color: "#9C27B0", Stroke: "none", type: "json" , body: [{from: 0, to: 0, content: ""}] }
             if (Array.isArray(subJson?.body)) return { success: true, data: subJson.body };
             if (Array.isArray(subJson)) return { success: true, data: subJson };
             return { error: 'UNKNOWN_JSON', data: subJson };
         } catch (e) {
             return { error: 'PARSE_FAILED', text: text.substring(0, 100) };
         }
      })()
    `;
        let items;
        try {
            items = await page.evaluate(fetchJs);
        }
        catch (err) {
            throw new CommandExecutionError(`字幕获取失败: ${err?.message || err}`);
        }
        if (items?.error) {
            throw new CommandExecutionError(`字幕获取失败: ${items.error}${items.text ? ' — ' + items.text : ''}`);
        }
        if (!items || typeof items !== 'object' || items.success !== true) {
            throw new CommandExecutionError('字幕获取结果对象不符合预期格式');
        }
        const finalItems = items.data;
        if (!Array.isArray(finalItems)) {
            throw new CommandExecutionError('解析到的字幕列表对象不符合数组格式');
        }
        if (finalItems.length === 0) {
            throw new EmptyResultError('bilibili subtitle', '字幕文件中没有字幕片段。');
        }
        // 5. 数据映射
        return finalItems.map((item, idx) => {
            const from = Number(item?.from);
            const to = Number(item?.to);
            if (!item || typeof item !== 'object' || !Number.isFinite(from) || !Number.isFinite(to)) {
                throw new CommandExecutionError('字幕片段缺少有效 from/to 时间戳');
            }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run to obtain a fresh subtitle_url and retry immediately.
  2. Check the embedded error text (after ' — ') for the HTTP status and act on it (403 → referer/auth issue, 404 → file gone).
  3. Retry from a different network/region if the CDN blocks your IP.
  4. Report/patch if Bilibili changed the subtitle JSON format causing parse errors.
Defensive patterns

Strategy: retry

Validate before calling

// If you control the fetch, check the response before parsing:
const res = await fetch(subUrl);
if (!res.ok) throw new Error(`CDN ${res.status}`);

Try / catch

try {
  await run('bilibili subtitle', { url });
} catch (e) {
  if (/字幕获取失败.*403|403/.test(e.message)) throw new Error('Subtitle URL expired or referer-blocked; refresh and retry.');
  if (/字幕获取失败/.test(e.message)) { await sleep(5000); return run('bilibili subtitle', { url }); }
  throw e;
}

Prevention

When it happens

Trigger: The fetchJs inside page.evaluate catches res not ok (e.g. 403/404 from the CDN because the signed subtitle_url expired or was region-blocked) or JSON.parse of the body throws.

Common situations: Stale/expired subtitle_url tokens; CDN 403 due to missing Referer handling; subtitle file removed from CDN; region-locked CDN edge nodes.

Related errors


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