tonhowtf/omniget · error
No video URL
Error message
No video URL
What it means
For video posts, native_download searches available_qualities for an entry labeled 'video'; if media info produced no such entry it cannot download and throws 'No video URL'. This is an internal invariant: a video-type MediaInfo should always carry a video quality entry.
Solutions
- Inspect parse_media to ensure every Video classification also pushes a quality entry with label "video".
- Log available_qualities when the lookup fails to see what labels were actually produced.
- Re-fetch media info fresh instead of caching MediaInfo across requests.
- Add a consistency check in parse_media: MediaType::Video must have >=1 'video' quality.
- Fall back to the post's direct video URL (media/ or DASH_96.mp4 style) when the labeled entry is absent.
Example fix
// before
let video_quality = info.available_qualities.iter()
.find(|q| q.label == "video")
.ok_or_else(|| anyhow!("No video URL"))?;
// after
let video_quality = info.available_qualities.iter().find(|q| q.label == "video")
.or_else(|| info.available_qualities.iter().find(|q| q.url.contains("DASH") || q.url.ends_with(".mp4")))
.ok_or_else(|| anyhow!("No video URL in qualities: {:?}",
info.available_qualities.iter().map(|q| &q.label).collect::<Vec<_>>()))?; Defensive patterns
Strategy: validation
Validate before calling
// sanity-check media info consistency before download
if info.media_type == MediaType::Video
&& !info.available_qualities.iter().any(|q| q.label == "video") {
return Err("media info missing video URL; re-fetch media info");
} Type guard
fn has_video_entry(info: &MediaInfo) -> bool {
info.available_qualities.iter().any(|q| q.label == "video" && !q.url.is_empty())
} Try / catch
match download(url, out).await {
Err(e) if e.to_string().contains("No video URL") => {
let fresh = get_media_info(url).await?; // re-fetch, don't use stale info
download_fresh(fresh, out).await
}
other => other,
} Prevention
- Ensure parse_media always pairs MediaType::Video with a 'video' quality entry
- Don't cache MediaInfo across requests — CDN URLs and labels can change
- Log available_qualities labels when the lookup fails
- Add an invariant check in parse_media so bad state fails at creation time
When it happens
Trigger: parse_media classified the post as MediaType::Video but failed to populate an available_qualities entry with label == "video" (e.g. missing fallback_url / HLS URL), or a schema change renamed/removed that field.
Common situations: Reddit posts with video but no DASH fallback_url (rare API responses); posts where video exists only as crosspost/gallery item; a regression in parse_media after a Reddit API change; reusing cached MediaInfo from another post type.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Nenhum URL GIF
- gallery-dl binary not found after download
- não foi possível resolver o link curto
- download failed without specific error
- No resolution available
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/f610cb5a22a6fc4e.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/src/platforms/reddit/mod.rs:544
file_size_bytes: None,
})
}
}
}
async fn native_download(
&self,
info: &MediaInfo,
opts: &DownloadOptions,
progress: mpsc::Sender<ProgressUpdate>,
) -> anyhow::Result<DownloadResult> {
match info.media_type {
MediaType::Video => {
let video_quality = info
.available_qualities
.iter()
.find(|q| q.label == "video")
.ok_or_else(|| anyhow!("No video URL"))?;
let audio_quality = info.available_qualities.iter().find(|q| q.label == "audio");
let has_audio = audio_quality.is_some();
let ffmpeg_available = ffmpeg::is_ffmpeg_available().await;
if has_audio && !ffmpeg_available {
tracing::warn!("[reddit] Video has separate audio but FFmpeg is not installed — downloading video without audio");
}
if has_audio {
let video_tmp = opts.output_dir.join(format!(
"{}_video_tmp.mp4",
sanitize_filename::sanitize(&info.title)
));
let audio_tmp = opts.output_dir.join(format!(
"{}_audio_tmp.mp4",
sanitize_filename::sanitize(&info.title)View on GitHub (pinned to 8600b91f42)