{"record":{"id":"cf822229d8306434","repo":"tonhowtf/omniget","slug":"yt-dlp-not-found-douyin","errorCode":null,"errorMessage":"yt-dlp not found","messagePattern":"yt-dlp not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/douyin.rs","lineNumber":189,"sourceCode":"#[async_trait]\nimpl PlatformDownloader for DouyinDownloader {\n    fn name(&self) -> &str {\n        \"douyin\"\n    }\n\n    fn can_handle(&self, url: &str) -> bool {\n        if let Ok(parsed) = url::Url::parse(url) {\n            if let Some(host) = parsed.host_str() {\n                return Self::host_matches(host);\n            }\n        }\n        false\n    }\n\n    async fn get_media_info(&self, url: &str) -> anyhow::Result<MediaInfo> {\n        let ytdlp_path = ytdlp::find_ytdlp_cached()\n            .await\n            .ok_or_else(|| anyhow!(\"yt-dlp not found\"))?;\n\n        let resolved = Self::resolve_url(url).await;\n        let extra = Self::extra_flags();\n        let json = ytdlp::get_video_info(&ytdlp_path, &resolved, &extra).await?;\n\n        let title = json\n            .get(\"title\")\n            .and_then(|v| v.as_str())\n            .unwrap_or(\"Douyin Video\")\n            .to_string();\n\n        let author = json\n            .get(\"uploader\")\n            .and_then(|v| v.as_str())\n            .or_else(|| json.get(\"channel\").and_then(|v| v.as_str()))\n            .unwrap_or(\"Unknown\")\n            .to_string();\n","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/douyin.rs#L171-L207","documentation":"Douyin's get_media_info delegates extraction to the external yt-dlp binary. Before doing anything else it calls ytdlp::find_ytdlp_cached(), and if that returns None — no yt-dlp executable was found in PATH or the known locations / cache — it fails with this anyhow error instead of attempting the extraction.","triggerScenarios":"Calling DouyinPlatform::get_media_info(url) when ytdlp::find_ytdlp_cached() resolves to no yt-dlp binary: yt-dlp not installed, not on PATH, or the cache lookup expired and re-discovery failed.","commonSituations":"Fresh dev machine or Docker image without yt-dlp; yt-dlp installed under a name the finder doesn't check; user removed the cached binary path between runs; packaging a Tauri app that assumes yt-dlp is bundled but isn't.","solutions":["Install yt-dlp (pip install yt-dlp, brew install yt-dlp, or download the standalone binary) and ensure it is on PATH.","Pass an explicit yt-dlp path in download options (opts.ytdlp_path) or pre-warm the cache via ytdlp::ensure_ytdlp(), which can auto-download the binary.","Verify with `yt-dlp --version` in the same environment the app runs in (check PATH inside GUI/Tauri processes, which often differ from shell PATH)."],"exampleFix":"// before\nlet ytdlp_path = ytdlp::find_ytdlp_cached()\n    .await\n    .ok_or_else(|| anyhow!(\"yt-dlp not found\"))?;\n// after\nlet ytdlp_path = match ytdlp::find_ytdlp_cached().await {\n    Some(p) => p,\n    None => ytdlp::ensure_ytdlp().await? // auto-download on first run\n};","handlingStrategy":"fallback","validationCode":"async fn check_ytdlp() -> bool {\n    tokio::process::Command::new(\"yt-dlp\")\n        .arg(\"--version\")\n        .output()\n        .await\n        .map(|o| o.status.success())\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match platform.get_media_info(url).await {\n    Err(e) if e.to_string().contains(\"yt-dlp not found\") => {\n        let path = ytdlp::ensure_ytdlp().await.context(\"installing yt-dlp\")?;\n        retry_with_ytdlp_path(url, path).await\n    }\n    other => other,\n}","preventionTips":["Call ytdlp::ensure_ytdlp() at application startup to install/cache the binary before first use.","Ship yt-dlp with your app bundle and pass its absolute path via opts.ytdlp_path.","Run a `yt-dlp --version` health check on startup and surface a clear setup message.","Remember GUI/Tauri processes may have a different PATH than your shell."],"tags":["yt-dlp","missing-dependency","rust","external-binary"],"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"}