{"record":{"id":"67778b4586ba713f","repo":"tonhowtf/omniget","slug":"no-hls-url-available","errorCode":null,"errorMessage":"No HLS URL available","messagePattern":"No HLS URL available","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/bluesky.rs","lineNumber":280,"sourceCode":"                    opts.filename_template.as_deref(),\n                    opts.referer.as_deref().or(Some(\"https://bsky.app\")),\n                    opts.cancel_token.clone(),\n                    None,\n                    opts.concurrent_fragments,\n                    false,\n                    &[],\n                    opts.audio_format.as_deref(),\n                )\n                .await;\n            }\n        }\n\n        match info.media_type {\n            MediaType::Video => {\n                let hls_url = &info\n                    .available_qualities\n                    .first()\n                    .ok_or_else(|| anyhow!(\"No HLS URL available\"))?\n                    .url;\n\n                let filename = format!(\"{}.mp4\", sanitize_filename::sanitize(&info.title));\n                let output_path = opts.output_dir.join(&filename);\n                let output_str = output_path.to_string_lossy().to_string();\n\n                let downloader =\n                    HlsDownloader::new().with_user_agent_override(opts.user_agent.clone());\n                let _ = progress.send(ProgressUpdate::percent(0.0)).await;\n\n                let result = downloader\n                    .download(\n                        hls_url,\n                        &output_str,\n                        \"https://bsky.app\",\n                        None,\n                        opts.cancel_token.clone(),\n                        20,","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/bluesky.rs#L262-L298","documentation":"Thrown in BlueskyDownloader::download for MediaType::Video when info.available_qualities is empty, so there is no HLS URL to feed the HLS downloader. The MediaInfo passed in is inconsistent with its media_type — a video entry must have at least one quality entry.","triggerScenarios":"Calling download() with a hand-constructed or yt-dlp-parsed MediaInfo whose media_type is Video but available_qualities is an empty vec, or after the single quality was stripped.","commonSituations":"Constructing MediaInfo programmatically and forgetting qualities, third-party code filtering qualities (e.g. by format) down to zero, or deserializing partial metadata.","solutions":["Check available_qualities is non-empty before calling download() with MediaType::Video.","Re-fetch media info via get_media_info to repopulate qualities.","If using the yt-dlp path, keep the quality with format == \"ytdlp\" so it routes correctly.","Validate MediaInfo (media_type vs qualities) at construction time."],"exampleFix":"// before\nlet info = MediaInfo { media_type: MediaType::Video, available_qualities: vec![], .. };\ndownloader.download(&info, &opts, tx).await?;\n// after\nassert!(!info.available_qualities.is_empty(), \"video MediaInfo needs at least one quality\");","handlingStrategy":"validation","validationCode":"if info.media_type == MediaType::Video && info.available_qualities.is_empty() {\n    return Err(anyhow!(\"video MediaInfo has no qualities; refetch via get_media_info\"));\n}","typeGuard":"fn has_video_qualities(info: &MediaInfo) -> bool {\n    matches!(info.media_type, MediaType::Video) && info.available_qualities.iter().any(|q| !q.url.is_empty())\n}","tryCatchPattern":"match downloader.download(&info, &opts, tx).await {\n    Err(e) if e.to_string() == \"No HLS URL available\" => {\n        let fresh = downloader.get_media_info(&original_url).await?;\n        downloader.download(&fresh, &opts, tx).await\n    }\n    other => other,\n}","preventionTips":["Never construct Video-typed MediaInfo with an empty available_qualities vec","Re-fetch media info rather than hand-editing quality lists","Add a constructor/validator that enforces media_type/qualities consistency"],"tags":["bluesky","download","empty-list"],"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"}