{"record":{"id":"88ca2e3e65dd95f5","repo":"tonhowtf/omniget","slug":"no-url-available-direct-file","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/direct_file.rs","lineNumber":219,"sourceCode":"            media_type: MediaType::File,\n            file_size_bytes,\n        })\n    }\n\n    async fn download(\n        &self,\n        info: &MediaInfo,\n        opts: &DownloadOptions,\n        progress: mpsc::Sender<ProgressUpdate>,\n    ) -> anyhow::Result<DownloadResult> {\n        let _ = progress.send(ProgressUpdate::percent(0.0)).await;\n\n        let file_url = info\n            .available_qualities\n            .first()\n            .map(|q| q.url.as_str())\n            .filter(|u| !u.is_empty())\n            .ok_or_else(|| anyhow!(\"No URL available\"))?;\n\n        let filename = sanitize_filename::sanitize(&info.title);\n        let filename = if filename.is_empty() {\n            filename_from_url(file_url)\n        } else {\n            filename\n        };\n        let output_path = opts.output_dir.join(&filename);\n\n        let mut builder = http_client::apply_global_proxy(reqwest::Client::builder())\n            .connect_timeout(std::time::Duration::from_secs(30));\n\n        if let Some(ua) = opts.user_agent.as_deref() {\n            builder = builder.user_agent(ua);\n        }\n\n        let jar =\n            crate::core::cookie_parser::load_extension_cookies_for_url(file_url).or_else(|| {","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/direct_file.rs#L201-L237","documentation":"Thrown in DirectFileDownloader::download when no usable URL can be derived: either available_qualities is empty, or the first entry's URL is an empty string (the .filter(|u| !u.is_empty()) drops it). The downloader has nothing to fetch.","triggerScenarios":"download() called with a MediaInfo whose available_qualities is empty, or whose first quality URL is \"\" (e.g. metadata was parsed from a page with no direct file link).","commonSituations":"Direct-file entries built from pages that failed to expose a media URL, partially populated MediaInfo structs, or callers stripping qualities before handing them to the downloader.","solutions":["Ensure available_qualities contains an entry with a non-empty url before calling download().","Re-run the page scrape / get_media_info to recover the direct URL.","Check the source URL actually points to a downloadable file (not an HTML page).","Validate MediaInfo in the caller and show a user-facing 'no downloadable URL' message."],"exampleFix":"// before\nlet info = MediaInfo { available_qualities: vec![VideoQuality { url: String::new(), .. }], .. };\ndownloader.download(&info, &opts, tx).await?;\n// after\nif info.available_qualities.first().map_or(true, |q| q.url.is_empty()) {\n    return Err(anyhow!(\"refusing to download: no direct file URL resolved\"));\n}","handlingStrategy":"validation","validationCode":"let has_url = info.available_qualities.first().map_or(false, |q| !q.url.is_empty());\nif !has_url {\n    return Err(anyhow!(\"no direct file URL; re-scrape the source page\"));\n}","typeGuard":"fn has_direct_url(info: &MediaInfo) -> bool {\n    info.available_qualities.first().map_or(false, |q| !q.url.is_empty())\n}","tryCatchPattern":"match downloader.download(&info, &opts, tx).await {\n    Err(e) if e.to_string() == \"No URL available\" => {\n        eprintln!(\"source page exposed no direct file URL; check the link\");\n    }\n    other => other,\n}","preventionTips":["Verify the source URL actually resolves to a file, not an HTML page","Never leave quality URL fields empty when building MediaInfo","Re-scrape rather than downloading from stale/partial metadata"],"tags":["direct-download","empty-list","url"],"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"}