jackwener/OpenCLI · error · CommandExecutionError
字幕 URL 非法: ${finalUrl}
Error message
字幕 URL 非法: ${finalUrl} What it means
A CommandExecutionError thrown when the resolved subtitle URL does not match /^https?:\/\// after protocol normalization. The library already prepends 'https:' to protocol-relative '//...' URLs, so a non-http(s) value means the API returned something unrecognizable as a fetchable URL.
Source
Thrown at clis/bilibili/subtitle.js:82
if (needLoginSubtitle) {
throw new AuthRequiredError('bilibili.com', 'Bilibili subtitles are hidden behind login for this video. Please log in to bilibili.com in Chrome and retry.');
}
throw new EmptyResultError('bilibili subtitle', '此视频没有发现外挂或智能字幕。');
}
// 3. 选择目标字幕语言
const target = kwargs.lang
? subtitles.find((s) => s.lan === kwargs.lang) || subtitles[0]
: subtitles[0];
if (!target || typeof target !== 'object' || !Object.hasOwn(target, 'subtitle_url')) {
throw new CommandExecutionError('字幕条目缺少 subtitle_url 字段');
}
const targetSubUrl = typeof target.subtitle_url === 'string' ? target.subtitle_url.trim() : '';
if (!targetSubUrl) {
throw new AuthRequiredError('bilibili.com', '[风控拦截/未登录] 获取到的 subtitle_url 为空!请确保 CLI 已成功登录且风控未封锁此账号。');
}
const finalUrl = targetSubUrl.startsWith('//') ? 'https:' + targetSubUrl : targetSubUrl;
if (!/^https?:\/\//i.test(finalUrl)) {
throw new CommandExecutionError(`字幕 URL 非法: ${finalUrl}`);
}
// 4. 解析并拉取 CDN 的 JSON 文件
const fetchJs = `
(async () => {
const url = ${JSON.stringify(finalUrl)};
const res = await fetch(url);
const text = await res.text();
if (text.startsWith('<!DOCTYPE') || text.startsWith('<html')) {
return { error: 'HTML', text: text.substring(0, 100), url };
}
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 };View on GitHub (pinned to 49907e53dc)
Solutions
- Inspect the raw player API response to see what subtitle_url actually contains.
- Re-run the request — if it's transient data corruption it may resolve.
- Update the library if Bilibili changed the URL format (e.g. new scheme).
- As a workaround, patch/normalize the URL yourself before fetch if you control the pipeline.
Example fix
// before
const finalUrl = targetSubUrl.startsWith('//') ? 'https:' + targetSubUrl : targetSubUrl;
// after
const finalUrl = targetSubUrl.startsWith('//')
? 'https:' + targetSubUrl
: targetSubUrl.startsWith('/') ? 'https://api.bilibili.com' + targetSubUrl : targetSubUrl; Defensive patterns
Strategy: validation
Validate before calling
const isHttpUrl = (u) => typeof u === 'string' && /^https?:\/\//i.test(u.startsWith('//') ? 'https:' + u : u);
if (!isHttpUrl(track.subtitle_url)) throw new Error('bad subtitle url'); Type guard
const isHttpUrl = (u) => typeof u === 'string' && /^https?:\/\//i.test(u);
Try / catch
try {
await run('bilibili subtitle', { url });
} catch (e) {
if (/字幕 URL 非法/.test(e.message)) throw new Error(`Upstream returned invalid subtitle URL; raw response should be inspected: ${e.message}`);
throw e;
} Prevention
- Keep the library updated for URL format changes in the API.
- Log raw player API responses when debugging URL issues.
- Disable response-rewriting proxies/interceptors for bilibili domains.
When it happens
Trigger: target.subtitle_url contains a non-URL string (e.g. a relative path, placeholder text, or corrupted value) that doesn't start with '//' or 'http(s)://'.
Common situations: Bilibili API schema changes; proxies or response interceptors mangling the URL field; bogus data from cached/intercepted responses.
Related errors
- 字幕片段缺少有效 from/to 时间戳
- Bilibili ${label} API returned malformed top_replies
- Bilibili comments reply ${index + 1} was malformed
- Bilibili comments reply ${index + 1} was missing rpid
- Bilibili comments reply ${index + 1} was missing ctime
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/b54a48ada80e33f5.
Report an issue: GitHub.