{"record":{"id":"b7338a8f2328c0d7","repo":"tonhowtf/omniget","slug":"yt-dlp-not-found","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/bilibili/legacy.rs","lineNumber":70,"sourceCode":"    }\n    if parts.next() != Some(\"lists\") {\n        return false;\n    }\n    let sid = parts.next().unwrap_or(\"\");\n    !sid.is_empty() && sid.chars().all(|c| c.is_ascii_digit())\n}\n\npub fn bilibili_extra_flags() -> Vec<String> {\n    vec![\n        \"--referer\".to_string(),\n        \"https://www.bilibili.com\".to_string(),\n    ]\n}\n\npub async fn get_media_info(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 extra = bilibili_extra_flags();\n\n    if is_playlist_or_series(url) {\n        let (title, entries) = ytdlp::get_playlist_info(&ytdlp_path, url, &extra).await?;\n\n        if entries.is_empty() {\n            return Err(anyhow!(\"Playlist empty or unavailable\"));\n        }\n\n        let qualities: Vec<MediaVideoQuality> = entries\n            .iter()\n            .enumerate()\n            .map(|(i, e)| MediaVideoQuality {\n                label: format!(\"{}. {}\", i + 1, e.title),\n                width: 0,\n                height: 0,\n                url: e.url.clone(),","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/bilibili/legacy.rs#L52-L88","documentation":"get_media_info for Bilibili resolves the yt-dlp binary via ytdlp::find_ytdlp_cached(); if no yt-dlp executable is found (cached lookup returns None), it aborts with 'yt-dlp not found'. The Bilibili backend depends entirely on yt-dlp for extraction.","triggerScenarios":"Calling get_media_info before yt-dlp has been downloaded/bundled: find_ytdlp_cached() checks known paths and app cache and finds nothing.","commonSituations":"First run without completing dependency setup, users who deleted the app's yt-dlp cache, Linux installs without yt-dlp in PATH, or PATH differences between terminal and GUI launch.","solutions":["Install yt-dlp in Settings → Dependencies (the app can self-download it)","Install yt-dlp system-wide (pip install yt-dlp) and ensure it is on PATH","Verify `yt-dlp --version` resolves in the environment the app runs from","Clear/rebuild the app's dependency cache so find_ytdlp_cached re-detects it"],"exampleFix":"// before\nlet ytdlp_path = ytdlp::find_ytdlp_cached().await.ok_or_else(|| anyhow!(\"yt-dlp not found\"))?;\n// after\n// ensure dependency setup ran first:\n//   app ensures yt-dlp exists (download to cache) before calling get_media_info\nlet ytdlp_path = ensure_ytdlp_available().await?;","handlingStrategy":"validation","validationCode":"// check yt-dlp availability before calling get_media_info\nif ytdlp::find_ytdlp_cached().await.is_none() {\n    return Err(anyhow!(\"Run dependency setup: install yt-dlp first\"));\n}","typeGuard":null,"tryCatchPattern":"match get_media_info(url).await {\n    Err(e) if e.to_string() == \"yt-dlp not found\" => prompt_dependency_install(),\n    other => other,\n}","preventionTips":["Check/install yt-dlp during app initialization","Expose a dependency status screen in Settings","Verify PATH in GUI launches (differs from terminal)","Re-check the cache after app updates"],"tags":["yt-dlp","missing-dependency","bilibili","environment"],"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"}