{"record":{"id":"bdc8552fa9f2ae45","repo":"tonhowtf/omniget","slug":"failed-to-parse-content","errorCode":null,"errorMessage":"Failed to parse content: {}","messagePattern":"Failed to parse content: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/bilibili/mod.rs","lineNumber":247,"sourceCode":"    if url.is_empty() {\n        return Err(anyhow!(\"No URL available\"));\n    }\n\n    let slug = active_account_slug();\n    let client = build_api_client(slug.as_deref(), opts.user_agent.as_deref())?;\n\n    let mut effective_url = url.to_string();\n    if url_kind::is_b23_short(&effective_url) {\n        if let Ok(resolved) = url_kind::resolve_b23(&client, &effective_url).await {\n            effective_url = resolved;\n        }\n    }\n\n    let kind = url_kind::detect(&effective_url)\n        .map_err(|e| anyhow!(\"Failed to detect URL kind: {}\", e.i18n_key()))?;\n    let parsed = parser::parse(&client, &kind)\n        .await\n        .map_err(|e| anyhow!(\"Failed to parse content: {}\", e.i18n_key()))?;\n\n    let settings = runtime_settings();\n    let container = mux::container_from_setting(&settings.download.bilibili_container);\n    let danmaku_format = danmaku_format_from_setting(&settings.download.bilibili_danmaku_format);\n    let cover_format = cover::CoverFormat::from_str(&settings.download.bilibili_cover_format);\n    let template_set = naming::TemplateSet {\n        video: settings.download.bilibili_naming_video.clone(),\n        multi_part: settings.download.bilibili_naming_multi_part.clone(),\n        bangumi: settings.download.bilibili_naming_bangumi.clone(),\n        cheese: settings.download.bilibili_naming_cheese.clone(),\n        collection: settings.download.bilibili_naming_collection.clone(),\n    };\n    let first_item_owned = parsed.items.first().cloned().unwrap_or_default();\n    let naming_kind = naming::classify(&kind, &first_item_owned);\n    let naming_inputs = naming::NamingInputs {\n        item: &first_item_owned,\n        metadata: &parsed.metadata,\n        parsed_title: &parsed.title,","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/bilibili/mod.rs#L229-L265","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet parsed = parser::parse(&client, &kind).await.map_err(|e| anyhow!(\"Failed to parse content: {}\", e.i18n_key()))?;\n// after\nlet parsed = parser::parse(&client, &kind).await.with_context(||\n    format!(\"bilibili content parse failed for {} (check login/account or content availability)\", effective_url))?;","handlingStrategy":"retry","validationCode":"// pre-flight: verify the content is fetchable\nif let Err(e) = quick_check_video_exists(url).await { return Err(anyhow!(\"content unavailable: {}\", e)); }","typeGuard":null,"tryCatchPattern":"match download(url).await {\n    Err(e) if e.to_string().contains(\"Failed to parse content\") => {\n        if is_rate_limit(&e) { backoff_and_retry(url, 3).await } else { report(e) }\n    }\n    other => other,\n}","preventionTips":["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."],"tags":["bilibili","api","parsing","upstream"],"backgroundTag":"api-error-response","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}