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
- Re-run to obtain a fresh subtitle_url and retry immediately.
- Check the embedded error text (after ' — ') for the HTTP status and act on it (403 → referer/auth issue, 404 → file gone).
- Retry from a different network/region if the CDN blocks your IP.
- 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
- Fetch the subtitle file immediately after obtaining subtitle_url.
- Watch the HTTP status embedded after ' — ' in the message.
- Retry from another region/IP if CDN blocks yours.
- Keep the library current for subtitle JSON format changes.
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
- HTTP ${res.status} from signed CDN URL while downloading ${i
- Bilibili creator comparison request failed: ${detail}
- 此视频没有发现外挂或智能字幕。
- 字幕条目缺少 subtitle_url 字段
- 字幕 URL 非法: ${finalUrl}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/816486053c31d4ef.
Report an issue: GitHub.