tonhowtf/omniget · error

Could not extract YouTube video ID

Error message

Could not extract YouTube video ID

What it means

Thrown by YouTubeDownloader::fetch_with_ytdlp when Self::extract_video_id(url) returns None for a non-playlist URL. It means the URL does not match any supported YouTube video URL shape, so the video ID cannot be parsed out of it.

Solutions

  1. Validate that the input is a YouTube watch/shorts/youtu.be URL before calling fetch_with_ytdlp.
  2. Normalize the URL: strip surrounding text, scheme, and unnecessary query parameters.
  3. Run Self::extract_video_id(url) as a pre-check and show a user-facing 'invalid YouTube URL' message on None.
  4. Extend extract_video_id to cover additional URL shapes (shorts, embed, live) if users commonly submit them.

Example fix

// before
let _video_id = Self::extract_video_id(url)
    .ok_or_else(|| anyhow!("Could not extract YouTube video ID"))?;
// after: normalize before extracting
let cleaned = url.trim().split_whitespace().next().unwrap_or("");
let _video_id = Self::extract_video_id(cleaned)
    .ok_or_else(|| anyhow!("Could not extract YouTube video ID from '{}'", cleaned))?;
Defensive patterns

Strategy: type-guard

Validate before calling

if !youtube_url_is_valid(user_input) {
    return Err(anyhow!("please paste a valid YouTube video URL (watch, youtu.be, or shorts)"));
}
fn youtube_url_is_valid(url: &str) -> bool {
    url.contains("youtube.com/watch") || url.contains("youtu.be/") || url.contains("youtube.com/shorts/")
}

Type guard

fn has_extractable_video_id(url: &str) -> bool {
    YouTubeDownloader::extract_video_id(url.trim()).is_some()
}

Try / catch

match YouTubeDownloader::extract_video_id(url.trim()) {
    Some(id) => proceed_with(id),
    None => {
        eprintln!("invalid YouTube URL: '{}' — expected a watch/youtu.be/shorts link", url);
        return;
    }
}

Prevention

When it happens

Trigger: Calling fetch_with_ytdlp with a non-YouTube URL, a YouTube URL in an unsupported shape (e.g. youtu.be with extra junk, /shorts/ variants if unhandled, mangled query strings), or an empty/whitespace string.

Common situations: Users pasting search-result pages, channel URLs, or music.youtube.com links; URLs wrapped in extra text; regional YouTube domains the extractor doesn't recognize; mobile share links with redirects.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/453aa933c1d95af6. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/src/platforms/youtube/mod.rs:115

                    url: entry.url,
                    format: "ytdlp_playlist".to_string(),
                })
                .collect();

            return Ok(MediaInfo {
                title: sanitize_filename::sanitize(&playlist_title),
                author: playlist_title,
                platform: "youtube".to_string(),
                duration_seconds: None,
                thumbnail_url: None,
                available_qualities: qualities,
                media_type: MediaType::Playlist,
                file_size_bytes: None,
            });
        }

        let _video_id = Self::extract_video_id(url)
            .ok_or_else(|| anyhow!("Could not extract YouTube video ID"))?;

        let json = ytdlp::get_video_info(ytdlp_path, url, &[]).await?;
        Self::parse_video_info(&json)
    }

    fn extract_quality_height(quality_str: &str) -> Option<u32> {
        let s = quality_str.trim().to_lowercase();
        if s == "best" || s == "highest" {
            return None;
        }
        s.trim_end_matches('p').parse::<u32>().ok()
    }

    pub fn parse_video_info(json: &serde_json::Value) -> anyhow::Result<MediaInfo> {
        let video_id = json
            .get("id")
            .and_then(|v| v.as_str())
            .unwrap_or("unknown")

View on GitHub (pinned to 8600b91f42)