tonhowtf/omniget · error
Failed to parse content
Error message
Failed to parse content: {} What it means
After URL classification succeeds, api_engine_download() calls parser::parse(&client, &kind) to fetch and parse the bilibili content (video metadata, streams). If parsing fails, the error is wrapped with its i18n key. This covers API-level failures: bad API responses, rate limits, auth failures, or deleted content.
Solutions
- Configure an active bilibili account (cookies) and retry, especially for members-only content.
- Check the video URL in a browser — if it 404s or shows a region/audit notice, the content is unavailable.
- Retry after a delay if rate-limited; avoid hammering anonymous requests.
- Inspect parser::parse to confirm it matches the current bilibili API response schema.
Example fix
// before
let parsed = parser::parse(&client, &kind).await.map_err(|e| anyhow!("Failed to parse content: {}", e.i18n_key()))?;
// after
let parsed = parser::parse(&client, &kind).await.with_context(||
format!("bilibili content parse failed for {} (check login/account or content availability)", effective_url))?; Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: verify the content is fetchable
if let Err(e) = quick_check_video_exists(url).await { return Err(anyhow!("content unavailable: {}", e)); } Try / catch
match download(url).await {
Err(e) if e.to_string().contains("Failed to parse content") => {
if is_rate_limit(&e) { backoff_and_retry(url, 3).await } else { report(e) }
}
other => other,
} Prevention
- Configure bilibili account cookies for login-required content.
- Verify the video URL resolves in a browser before downloading.
- Throttle anonymous requests to avoid bilibili rate limits.
- Keep the parser in sync with bilibili API schema changes.
When it happens
Trigger: download() -> api_engine_download() where parser::parse returns Err — bilibili API returned an error (deleted video, region lock, missing cookies, rate limit) or an unexpected response body.
Common situations: Video removed or under review; members-only content fetched without an account cookie; bilibili API rate-limiting anonymous requests; bilibili changed an API endpoint/field and the parser no longer matches.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse content
- não reconheci um vídeo do Bilibili em
- No URL available
- YouTube não retornou URL
- HTTP
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/bdc8552fa9f2ae45.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/platforms/bilibili/mod.rs:247
if url.is_empty() {
return Err(anyhow!("No URL available"));
}
let slug = active_account_slug();
let client = build_api_client(slug.as_deref(), opts.user_agent.as_deref())?;
let mut effective_url = url.to_string();
if url_kind::is_b23_short(&effective_url) {
if let Ok(resolved) = url_kind::resolve_b23(&client, &effective_url).await {
effective_url = resolved;
}
}
let kind = url_kind::detect(&effective_url)
.map_err(|e| anyhow!("Failed to detect URL kind: {}", e.i18n_key()))?;
let parsed = parser::parse(&client, &kind)
.await
.map_err(|e| anyhow!("Failed to parse content: {}", e.i18n_key()))?;
let settings = runtime_settings();
let container = mux::container_from_setting(&settings.download.bilibili_container);
let danmaku_format = danmaku_format_from_setting(&settings.download.bilibili_danmaku_format);
let cover_format = cover::CoverFormat::from_str(&settings.download.bilibili_cover_format);
let template_set = naming::TemplateSet {
video: settings.download.bilibili_naming_video.clone(),
multi_part: settings.download.bilibili_naming_multi_part.clone(),
bangumi: settings.download.bilibili_naming_bangumi.clone(),
cheese: settings.download.bilibili_naming_cheese.clone(),
collection: settings.download.bilibili_naming_collection.clone(),
};
let first_item_owned = parsed.items.first().cloned().unwrap_or_default();
let naming_kind = naming::classify(&kind, &first_item_owned);
let naming_inputs = naming::NamingInputs {
item: &first_item_owned,
metadata: &parsed.metadata,
parsed_title: &parsed.title,View on GitHub (pinned to 8600b91f42)