{"record":{"id":"88ce48d5e4d2ff63","repo":"tonhowtf/omniget","slug":"timeout-fetching-playlist-120s","errorCode":null,"errorMessage":"Timeout fetching playlist (120s)","messagePattern":"Timeout fetching playlist \\(120s\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/ytdlp.rs","lineNumber":2586,"sourceCode":"    }\n\n    append_metadata_cookie_args(&mut args, url, extra_flags, \"playlist info\");\n\n    args.extend(proxy_args());\n    args.extend(extra_flags.iter().cloned());\n    args.push(url.to_string());\n\n    let _slot = acquire_ytdlp_slot(\"playlist info\").await;\n    let output = tokio::time::timeout(\n        std::time::Duration::from_secs(120),\n        ytdlp_command(ytdlp)\n            .args(&args)\n            .stdout(Stdio::piped())\n            .stderr(Stdio::piped())\n            .output(),\n    )\n    .await\n    .map_err(|_| anyhow!(\"Timeout fetching playlist (120s)\"))?\n    .map_err(|e| anyhow!(\"Failed to run yt-dlp: {}\", e))?;\n\n    if !output.status.success() {\n        let stderr = String::from_utf8_lossy(&output.stderr);\n        let stderr_lower = stderr.to_lowercase();\n        if stderr_lower.contains(\"http error 429\") {\n            rate_limit_429_increment();\n            let sanitized_url = sanitize_log_line(url);\n            let player_client = if is_youtube_url(url) {\n                \"default\"\n            } else {\n                \"n/a\"\n            };\n            tracing::warn!(\n                \"[yt-429] rate limit in get_playlist_info: url={} player_client={} retries=3\",\n                sanitized_url,\n                player_client\n            );","sourceCodeStart":2568,"sourceCodeEnd":2604,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/ytdlp.rs#L2568-L2604","documentation":"In get_playlist_info, the yt-dlp `.output()` call is wrapped in tokio::time::timeout with a fixed 120-second budget; if the playlist fetch exceeds it, the future is dropped and this error returned. Playlist enumeration (many entries) is much slower than single-video info, so this cap is easier to hit.","triggerScenarios":"Calling get_playlist_info on a large playlist (hundreds of entries) where yt-dlp's flat extraction exceeds 120s; slow network to the hosting site; yt-dlp hanging on rate limiting or bot-check pages.","commonSituations":"Very large YouTube playlists on throttled connections; sites requiring slow challenge solving; proxy latency; 429 rate-limiting causing yt-dlp to back off past the timeout.","solutions":["Split very large playlists into chunks and fetch them in batches under 120s each","Ensure yt-dlp is up to date and uses fast flat extraction (e.g. --flat-playlist) for listing","Check for 429 rate limiting (the code tracks it) and back off / use cookies if needed","Increase the timeout for large playlists or make it proportional to expected entry count"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Estimate playlist size first with a short flat probe before the full fetch\nlet probe = tokio::time::timeout(\n    std::time::Duration::from_secs(30),\n    ytdlp_command(ytdlp).args([\"--flat-playlist\", \"--playlist-items\", \"1\", \"--dump-json\", url]).output(),\n).await;\nif probe.is_err() { return Err(\"playlist source too slow; check network or split playlist\".into()); }","typeGuard":null,"tryCatchPattern":"match get_playlist_info(url).await {\n    Err(e) if e.to_string().contains(\"Timeout fetching playlist\") => {\n        // retry with chunked fetching or a larger budget\n    }\n    other => other,\n}","preventionTips":["Use --flat-playlist for listing to avoid per-video extraction cost","Scale the timeout with playlist size instead of a fixed 120s","Respect 429 backoff signals before retrying so yt-dlp does not stall internally","Warn users that very large playlists may need chunked fetching"],"tags":["rust","ytdlp","timeout","playlist"],"backgroundTag":"request-timeout","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"}