{"record":{"id":"ef3c1758d46027d6","repo":"tonhowtf/omniget","slug":"no-url-available","errorCode":null,"errorMessage":"No URL available","messagePattern":"No URL available","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/bilibili/legacy.rs","lineNumber":218,"sourceCode":"    progress: mpsc::Sender<ProgressUpdate>,\n) -> anyhow::Result<DownloadResult> {\n    let _ = progress.send(ProgressUpdate::percent(0.0)).await;\n\n    let ytdlp_path = match &opts.ytdlp_path {\n        Some(p) => p.clone(),\n        None => ytdlp::find_ytdlp_cached()\n            .await\n            .ok_or_else(|| anyhow!(\"yt-dlp not found\"))?,\n    };\n\n    let url = info\n        .available_qualities\n        .first()\n        .map(|q| q.url.as_str())\n        .unwrap_or(\"\");\n\n    if url.is_empty() {\n        return Err(anyhow!(\"No URL available\"));\n    }\n\n    if info.media_type == MediaType::Playlist {\n        return download_playlist(info, opts, progress, &ytdlp_path).await;\n    }\n\n    let quality_height = opts\n        .quality\n        .as_ref()\n        .and_then(|q| q.trim_end_matches('p').parse::<u32>().ok());\n\n    let extra = vec![\"--no-playlist\".to_string()];\n\n    ytdlp::download_video(\n        &ytdlp_path,\n        url,\n        &opts.output_dir,\n        quality_height,","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/bilibili/legacy.rs#L200-L236","documentation":"download() pulls the first entry from info.available_qualities and falls back to an empty string when the list is empty; if the resulting URL is empty it refuses to proceed. This guard exists because the media-info parse succeeded but contained no downloadable stream URL, so any further download step would fail later with a less clear message.","triggerScenarios":"Calling download() (bilibili legacy path) with a MediaInfo whose available_qualities is empty, or whose first quality entry has url == \"\".","commonSituations":"The bilibili page/video resolved to no playable streams (region-locked, deleted/audit-pending video, membership-only content fetched without login cookies), or the upstream info extractor changed its response shape and quality extraction silently produced nothing.","solutions":["Verify the video is publicly accessible in your region/account and that login cookies (account slug) are configured if the content requires them.","Check how available_qualities is populated upstream (the media-info/parse step) and log the parsed MediaInfo to confirm extraction succeeded.","Return a user-facing, actionable error earlier (at info-extraction time) instead of an empty string default."],"exampleFix":"// before\nlet url = info.available_qualities.first().map(|q| q.url.as_str()).unwrap_or(\"\");\n// after\nlet url = info.available_qualities.first().map(|q| q.url.as_str())\n    .filter(|u| !u.is_empty())\n    .ok_or_else(|| anyhow!(\"No playable stream URL was extracted; the video may be region-locked, deleted, or require login\"))?;","handlingStrategy":"validation","validationCode":"if info.available_qualities.iter().any(|q| !q.url.is_empty()) { download(info, opts, progress).await?; } else { eprintln!(\"no playable streams extracted; check login/region\"); }","typeGuard":"fn has_downloadable_url(info: &MediaInfo) -> bool { info.available_qualities.first().map_or(false, |q| !q.url.is_empty()) }","tryCatchPattern":null,"preventionTips":["Always check available_qualities is non-empty before calling download().","Configure bilibili account cookies for members-only content.","Log the parsed MediaInfo when a download starts to catch silent extraction failures."],"tags":["bilibili","download","empty-url","media-extraction"],"backgroundTag":"empty-required-field","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"}