tonhowtf/omniget · info
Download cancelled
Error message
Download cancelled
What it means
During YouTube playlist downloads (youtube.rs download_playlist), the loop over playlist entries checks opts.cancel_token at the top of each iteration and bails if cancelled. Unlike per-video cancellation, this fires before starting a new entry, so completed videos are kept.
Solutions
- This is an intentional abort — catch it, report partial success (success_count), and clean up temp state.
- If only pausing is desired, implement a pause flag instead of cancelling the token.
- Check cancellation before calling download to avoid starting a playlist you'll immediately cancel.
Defensive patterns
Strategy: try-catch
Validate before calling
if opts.cancel_token.is_cancelled() {
return; // don't start a playlist that is already cancelled
} Try / catch
match download(url, opts).await {
Err(e) if e.to_string() == "Download cancelled" => report_partial(success_count, total),
other => other?,
} Prevention
- Use a pause flag for pause/resume instead of the cancel token
- Report partial success counts on cancellation
- Don't reuse a cancelled token for a new playlist run
When it happens
Trigger: Cancelling the cancel_token while a playlist download loop is between entries; calling download which delegates to download_playlist and then cancelling mid-playlist.
Common situations: User hits stop during a long playlist download; app shutdown triggers cancellation; UI cancels after N videos.
Related errors
- Download cancelled by user
- Send cancelled while waiting for receiver
- Send cancelled while paused
- Download cancelled
- Download cancelled during session creation
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/3cb19cba70c5270f.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/platforms/youtube.rs:368
opts: &DownloadOptions,
progress: mpsc::Sender<ProgressUpdate>,
ytdlp_path: &std::path::Path,
quality_height: Option<u32>,
) -> anyhow::Result<DownloadResult> {
let playlist_dir = opts
.output_dir
.join(sanitize_filename::sanitize(&info.title));
tokio::fs::create_dir_all(&playlist_dir).await?;
let total = info.available_qualities.len();
let mut total_bytes = 0u64;
let mut last_path = playlist_dir.clone();
let mut success_count = 0usize;
let mut last_err: Option<anyhow::Error> = None;
for (i, entry) in info.available_qualities.iter().enumerate() {
if opts.cancel_token.is_cancelled() {
anyhow::bail!("Download cancelled");
}
let (video_tx, mut video_rx) = mpsc::channel::<ProgressUpdate>(16);
let progress_tx = progress.clone();
let video_idx = i;
let video_total = total;
let forwarder = tokio::spawn(async move {
let mut max_pct = 0.0_f64;
while let Some(pu) = video_rx.recv().await {
max_pct = max_pct.max(pu.percent);
let overall = (video_idx as f64 / video_total as f64) * 100.0
+ (max_pct / video_total as f64);
let _ = progress_tx
.send(ProgressUpdate::rich(
overall,
None,
None,
pu.speed_bps,View on GitHub (pinned to 8600b91f42)