{"record":{"id":"c808a1c7b9851479","repo":"tonhowtf/omniget","slug":"yt-dlp-unavailable","errorCode":null,"errorMessage":"yt-dlp unavailable: {}","messagePattern":"yt-dlp unavailable: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/generic_ytdlp.rs","lineNumber":250,"sourceCode":"        \"generic\"\n    }\n\n    fn can_handle(&self, url: &str) -> bool {\n        if let Ok(parsed) = url::Url::parse(url) {\n            let scheme = parsed.scheme();\n            return scheme == \"http\" || scheme == \"https\";\n        }\n        false\n    }\n\n    async fn get_media_info(&self, url: &str) -> anyhow::Result<MediaInfo> {\n        if let Some(media_type) = is_direct_media_url(url) {\n            return Ok(build_direct_media_info(url, media_type));\n        }\n\n        let ytdlp_path = ytdlp::ensure_ytdlp()\n            .await\n            .map_err(|e| anyhow!(\"yt-dlp unavailable: {}\", e))?;\n\n        let extra = platform_extra_flags(url);\n        let json = ytdlp::get_video_info(&ytdlp_path, url, &extra).await?;\n        Self::parse_video_info(&json)\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 first = info\n            .available_qualities\n            .first()\n            .ok_or_else(|| anyhow!(\"No quality available\"))?;","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/generic_ytdlp.rs#L232-L268","documentation":"GenericYtdlpPlatform::get_media_info requires the yt-dlp binary for non-direct-media URLs. It calls ytdlp::ensure_ytdlp() (which may download yt-dlp); if that fails for any reason — no network, blocked download URL, missing system dependencies — the error is wrapped as 'yt-dlp unavailable: {e}'.","triggerScenarios":"get_media_info(url) where is_direct_media_url(url) is None and ytdlp::ensure_ytdlp() returns Err (binary absent AND auto-install failed, or the discovery itself errored).","commonSituations":"Air-gapped/offline environments where ensure_ytdlp can't download the binary; firewalls/proxies blocking downloads from GitHub releases; missing execute permission on the downloaded binary; unsupported platform/arch for prebuilt yt-dlp.","solutions":["Read the wrapped cause (the {e} payload) to distinguish install failure from discovery failure.","Install yt-dlp manually and put it on PATH so ensure_ytdlp finds it without downloading.","Fix network/proxy access to the yt-dlp release host, or vendor the binary and point config at it.","Ensure the binary has the executable bit (chmod +x) if it was downloaded manually."],"exampleFix":"// before\nlet ytdlp_path = ytdlp::ensure_ytdlp().await?; // may fail with 'yt-dlp unavailable: ...'\n// after\nlet ytdlp_path = match ytdlp::ensure_ytdlp().await {\n    Ok(p) => p,\n    Err(e) => {\n        eprintln!(\"yt-dlp bootstrap failed: {e}; falling back to PATH lookup\");\n        ytdlp::find_ytdlp_cached().await.ok_or_else(|| e)?\n    }\n};","handlingStrategy":"try-catch","validationCode":"// preflight\nlet ready = ytdlp::find_ytdlp_cached().await.is_some()\n    || std::env::var(\"PATH\").map(|p| p.contains(\"yt-dlp\")).unwrap_or(false);\nif !ready {\n    eprintln!(\"yt-dlp missing; will attempt auto-install (needs network)\");\n}","typeGuard":null,"tryCatchPattern":"match platform.get_media_info(url).await {\n    Err(e) if e.to_string().starts_with(\"yt-dlp unavailable\") => {\n        eprintln!(\"bootstrap failed: {e}; check network/exec permissions, then retry\");\n        Err(anyhow!(\"yt-dlp could not be provisioned: {e:#}\"))\n    }\n    other => other,\n}","preventionTips":["Pre-install yt-dlp in the deployment image so ensure_ytdlp never needs to download.","Whitelist the yt-dlp release host in firewalls/proxies used by CI.","Ensure downloaded binaries keep the executable bit in your packaging pipeline.","Persist the cached binary in a writable directory across restarts."],"tags":["yt-dlp","missing-dependency","rust","bootstrap"],"backgroundTag":"missing-dependency","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"}