tonhowtf/omniget · error

No video URL available

Error message

No video URL available

What it means

For MediaType::Video the library picks the first entry of info.available_qualities as the download source. If that list is empty — the scrape returned video metadata but no playable stream URLs — there is nothing to download and this error is thrown.

Solutions

  1. Re-fetch a fresh MediaInfo via get_media_info — play URLs expire quickly.
  2. Check whether the post is actually a video (photo posts have no video qualities).
  3. Retry with authenticated cookies so TikTok includes playAddr in the response.
  4. Ensure yt-dlp is installed so fallback quality extraction (yt-dlp-playable format) can populate the list.

Example fix

// before: blind download
let info = tiktok.get_media_info(url).await?;
tiktok.download(&info, &opts).await?;
// after: pre-validate qualities
let info = tiktok.get_media_info(url).await?;
if info.media_type == MediaType::Video && info.available_qualities.is_empty() {
    let info = tiktok.get_media_info(url).await?; // re-fetch fresh URLs
    anyhow::ensure!(!info.available_qualities.is_empty(), "No video URL available");
}
tiktok.download(&info, &opts).await?;
Defensive patterns

Strategy: validation

Validate before calling

let info = tiktok.get_media_info(url).await?;
anyhow::ensure!(
    info.media_type != MediaType::Video || !info.available_qualities.is_empty(),
    "No video URL available"
);

Type guard

fn has_video_url(info: &MediaInfo) -> bool {
    info.media_type != MediaType::Video || !info.available_qualities.is_empty()
}

Try / catch

match tiktok.download(&info, &opts).await {
    Err(e) if e.to_string() == "No video URL available" => {
        let fresh = tiktok.get_media_info(url).await?; // re-fetch: URLs may have expired
        tiktok.download(&fresh, &opts).await
    }
    other => other,
}

Prevention

When it happens

Trigger: download() is called with a MediaInfo whose media_type is Video but available_qualities is empty (quality extraction yielded no tiktok_direct or yt-dlp-playable URLs).

Common situations: TikTok serving the metadata but withholding playAddr for logged-out requests; region-blocked streams filtered out during quality extraction; photo/slideshow posts misdetected as Video; expired play URLs after a stale MediaInfo was cached.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/platforms/tiktok.rs:540

                    opts.concurrent_fragments,
                    false,
                    &[],
                    opts.audio_format.as_deref(),
                )
                .await;
            }
        }

        let cookies = self.captured_cookies.lock().await.clone();
        let mut headers = self.download_headers(&cookies);
        crate::core::http_client::inject_ua_header(&mut headers, opts.user_agent.as_deref());

        match info.media_type {
            MediaType::Video => {
                let quality = info
                    .available_qualities
                    .first()
                    .ok_or_else(|| anyhow!("No video URL available"))?;

                if quality.format == "tiktok_direct" {
                    let filename = format!("{}.mp4", sanitize_filename::sanitize(&info.title));
                    let output = opts.output_dir.join(&filename);

                    let result = direct_downloader::download_direct_with_headers(
                        &self.client,
                        &quality.url,
                        &output,
                        progress.clone(),
                        Some(headers),
                        Some(&opts.cancel_token),
                    )
                    .await;

                    match result {
                        Ok(bytes) => {
                            return Ok(DownloadResult {

View on GitHub (pinned to 8600b91f42)