{"record":{"id":"53c786ab613e0024","repo":"tonhowtf/omniget","slug":"playlist-empty-or-unavailable","errorCode":null,"errorMessage":"Playlist empty or unavailable","messagePattern":"Playlist empty or unavailable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/bilibili/legacy.rs","lineNumber":78,"sourceCode":"pub 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(),\n                format: \"mp4\".to_string(),\n            })\n            .collect();\n\n        return Ok(MediaInfo {\n            title,\n            author: \"Bilibili\".to_string(),\n            platform: \"bilibili\".to_string(),","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/bilibili/legacy.rs#L60-L96","documentation":"In get_media_info, when the URL is detected as a playlist/series, get_playlist_info is called and if the returned entries list is empty the function errors with 'Playlist empty or unavailable'. It means yt-dlp saw the URL as a playlist but returned zero usable items.","triggerScenarios":"is_playlist_or_series(url) is true, get_playlist_info succeeds, but entries.is_empty(): private/deleted playlists, region-locked collections, or playlists whose items were all removed.","commonSituations":"Sharing links to private Bilibili collections/favorites lists, deleted or made-private playlists, or scraper/anti-bot responses returning an empty item list.","solutions":["Open the playlist URL in a browser to confirm it is public and has items","Retry; anti-bot or transient failures can yield empty results","Update yt-dlp if Bilibili changed its playlist API shape","Pass cookies if the playlist requires login to view"],"exampleFix":"// before\nif entries.is_empty() {\n    return Err(anyhow!(\"Playlist empty or unavailable\"));\n}\n// after\nif entries.is_empty() {\n    tracing::warn!(\"playlist returned 0 entries for {url}\");\n    return Err(anyhow!(\"Playlist empty or unavailable\"));\n}","handlingStrategy":"try-catch","validationCode":"// ensure the playlist URL is publicly reachable first\nlet resp = reqwest::get(url).await?;\nif !resp.status().is_success() {\n    return Err(anyhow!(\"Playlist page not accessible ({})\", resp.status()));\n}","typeGuard":null,"tryCatchPattern":"match get_media_info(url).await {\n    Err(e) if e.to_string().contains(\"Playlist empty\") => {\n        eprintln!(\"Verify the playlist is public and has items, then retry\");\n    }\n    other => other,\n}","preventionTips":["Confirm playlists are public before programmatic use","Retry once on empty results (anti-bot flakiness)","Keep yt-dlp updated for Bilibili API changes","Support cookies for login-required collections"],"tags":["playlist","bilibili","empty-result","yt-dlp"],"backgroundTag":"empty-result-set","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"}