jackwener/OpenCLI · error · CommandExecutionError

字幕获取失败: ${err?.message || err}

Error message

字幕获取失败: ${err?.message || err}

What it means

A CommandExecutionError thrown when the in-page fetch of the subtitle CDN JSON file throws — the browser-side evaluate() rejected. The library wraps any page.evaluate failure and rethrows with the underlying message. This is about the network fetch of the subtitle file, not the earlier API call.

Source

Thrown at clis/bilibili/subtitle.js:111

         }

         try {
             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);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command to get a fresh subtitle_url — CDN tokens expire.
  2. Check network connectivity / proxy settings affecting Chrome.
  3. Increase browser/CLI timeouts if the page is being torn down mid-fetch.
  4. If persistent, verify the URL manually in Chrome and check for HTTP error status.
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: confirm Chrome can reach the CDN host before the run:
await fetch('https://api.bilibili.com/x/web-interface/nav', { method: 'HEAD' }).catch(() => { throw new Error('network unavailable'); });

Try / catch

try {
  await run('bilibili subtitle', { url });
} catch (e) {
  if (/字幕获取失败/.test(e.message)) {
    await sleep(5000);
    return run('bilibili subtitle', { url }); // fresh token, fresh fetch
  }
  throw e;
}

Prevention

When it happens

Trigger: page.evaluate(fetchJs) rejects: network failure reaching the CDN URL, CORS/blocked fetch inside the page context, page navigated/closed mid-evaluate, or the browser context was destroyed.

Common situations: Expired CDN signed URLs (subtitle_url tokens expire); offline/proxy network issues; browser tab closed by timeout; CDN returning errors that surface as fetch rejection (rare, usually fetch resolves with res.ok false).

Related errors


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