{"record":{"id":"ed217929c3496c50","repo":"tonhowtf/omniget","slug":"no-url-found-in-mediainfo-p2p","errorCode":null,"errorMessage":"No URL found in MediaInfo","messagePattern":"No URL found in MediaInfo","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/p2p.rs","lineNumber":110,"sourceCode":"                width: 0,\n                height: 0,\n                url: url.to_string(),\n                format: \"p2p\".to_string(),\n            }],\n            media_type: MediaType::Video,\n            file_size_bytes: None,\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 url = match info.available_qualities.first() {\n            Some(q) => &q.url,\n            None => anyhow::bail!(\"No URL found in MediaInfo\"),\n        };\n\n        let code = url\n            .strip_prefix(\"p2p:\")\n            .ok_or_else(|| anyhow!(\"Invalid P2P URL\"))?;\n\n        let _ = progress.send(ProgressUpdate::percent(-2.0)).await;\n\n        tracing::info!(\"[p2p] connecting to relay for code: {}\", code);\n\n        let stream = connect_relay().await?;\n        let (read_half, mut write_half) = tokio::io::split(stream);\n        let mut reader = BufReader::new(read_half);\n\n        write_half\n            .write_all(format!(\"RECV {}\\n\", code).as_bytes())\n            .await?;\n        write_half.flush().await?;","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/p2p.rs#L92-L128","documentation":"This error is thrown by the P2P download routine when the MediaInfo passed in has no entries in its available_qualities list, so there is no URL to download from. The library requires at least one quality entry whose .url field supplies the P2P transfer target (expected to look like 'p2p:<code>'). It is a guard against being asked to download from an empty/unresolved MediaInfo.","triggerScenarios":"Calling download() with a MediaInfo whose available_qualities vec is empty — typically because resolution of the P2P code produced no qualities, or a caller constructed MediaInfo manually without filling available_qualities.","commonSituations":"A platform resolver returned early/failed silently and produced an empty MediaInfo; a hand-built MediaInfo in tests or glue code; a parse of a share code that yielded no candidate URLs.","solutions":["Inspect the MediaInfo before calling download() and ensure available_qualities contains at least one entry with a valid 'p2p:' URL","Re-run the resolution step (resolve/get MediaInfo) that should populate available_qualities and surface its errors instead of swallowing them","Fix upstream code that constructs MediaInfo so it always appends the P2P quality URL"],"exampleFix":"// before\nlet info = MediaInfo { ..Default::default() }; // empty available_qualities\np2p::download(&info, &opts, tx).await?;\n// after\nlet info = p2p::resolve(&code).await?; // populates available_qualities\nif info.available_qualities.is_empty() {\n    anyhow::bail!(\"P2P code resolved to no downloadable qualities\");\n}\np2p::download(&info, &opts, tx).await?;","handlingStrategy":"validation","validationCode":"let url = info.available_qualities.first().map(|q| q.url.clone()).filter(|u| u.starts_with(\"p2p:\"));\nif url.is_none() {\n    anyhow::bail!(\"MediaInfo has no P2P quality URL; re-resolve the source first\");\n}","typeGuard":"fn has_p2p_url(info: &MediaInfo) -> bool {\n    info.available_qualities.first().map_or(false, |q| q.url.starts_with(\"p2p:\"))\n}","tryCatchPattern":null,"preventionTips":["Never hand-construct MediaInfo for downloads; always use the resolver API","Assert non-empty available_qualities in tests that exercise download()","Log the MediaInfo contents when download fails to spot empty resolution early"],"tags":["p2p","media-info","empty-state","download"],"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"}