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

  1. This is an intentional abort — catch it, report partial success (success_count), and clean up temp state.
  2. If only pausing is desired, implement a pause flag instead of cancelling the token.
  3. 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

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


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)