{"record":{"id":"ce7b2e66de1e5834","repo":"tonhowtf/omniget","slug":"no-downloadable-media-found-in-threads-post","errorCode":null,"errorMessage":"No downloadable media found in Threads post","messagePattern":"No downloadable media found in Threads post","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/threads.rs","lineNumber":482,"sourceCode":"                    thumbnail_url,\n                    available_qualities: qualities,\n                    media_type: MediaType::Carousel,\n                    file_size_bytes: None,\n                })\n            }\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 count = info.available_qualities.len();\n\n        if count == 0 {\n            return Err(anyhow!(\"No downloadable media found in Threads post\"));\n        }\n\n        if count == 1 {\n            let quality = info.available_qualities.first().unwrap();\n            let filename = format!(\n                \"{}.{}\",\n                sanitize_filename::sanitize(&info.title),\n                quality.format\n            );\n            let output = opts.output_dir.join(&filename);\n\n            let mut hdr_map = Self::threads_headers();\n            crate::core::http_client::inject_ua_header(&mut hdr_map, opts.user_agent.as_deref());\n            let headers = Some(hdr_map);\n\n            let bytes = download_direct_with_headers(\n                &self.client,\n                &quality.url,","sourceCodeStart":464,"sourceCodeEnd":500,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/threads.rs#L464-L500","documentation":"download in threads.rs inspects info.available_qualities.len() and raises this error when it is zero. It means a MediaInfo reached the download stage with no selectable quality/media entries, so there is nothing to download. Usually indicates get_media_info produced an empty quality list despite succeeding.","triggerScenarios":"Calling download with a Threads MediaInfo whose available_qualities is empty — e.g. extract_media_from_post built items but none were mapped into qualities, or the caller constructed MediaInfo manually.","commonSituations":"Schema changes making the quality-population step silently skip all items; race where the post's media was removed between info and download; callers reusing a MediaInfo from a different (media-less) post.","solutions":["Verify available_qualities is non-empty before calling download","Check the code path that populates available_qualities from extracted media for silent skips","Re-fetch media info (get_media_info) to get a fresh MediaInfo before downloading","Return a clearer 'media list empty, re-fetch info' error to the caller"],"exampleFix":"// before\nif count == 0 {\n    return Err(anyhow!(\"No downloadable media found in Threads post\"));\n}\n// after\nif count == 0 {\n    return Err(anyhow!(\"No downloadable media found in Threads post; re-fetch media info\"));\n}","handlingStrategy":"validation","validationCode":"if (!info || !Array.isArray(info.available_qualities) || info.available_qualities.length === 0) {\n  throw new Error(\"MediaInfo has no downloadable qualities; re-fetch media info first\");\n}","typeGuard":"function isDownloadable(info) {\n  return Array.isArray(info?.available_qualities) && info.available_qualities.length > 0;\n}","tryCatchPattern":"match threads.download(&info, tx).await {\n    Err(e) if e.to_string().contains(\"No downloadable media\") => {\n        // refresh info once, then retry\n        let fresh = threads.get_media_info(url).await?;\n        threads.download(&fresh, tx).await?;\n    }\n    other => other?,\n}","preventionTips":["Always obtain MediaInfo via get_media_info immediately before download","Assert available_qualities is non-empty in your pre-download checks","Re-fetch info if the post may have changed between steps","Instrument the quality-population code path to detect silent empty lists"],"tags":["threads","download","empty-list"],"backgroundTag":"empty-result-set","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"}