Zackriya-Solutions/meetily · info · anyhow::Error

Download cancelled by user

Error message

Download cancelled by user

What it means

Inside the streaming loop, each iteration checks cancel_download_flag; when it equals this model's name the loop exits, the model is removed from active_downloads, and this error propagates. It is intentional control flow for the Cancel button, not a failure — but it travels the Err channel, so callers must distinguish it from real failures.

Source

Thrown at frontend/src-tauri/src/whisper_engine/whisper_engine.rs:1017

        let mut downloaded = 0u64;
        let mut last_progress_report = 0u8;
        let mut last_report_time = std::time::Instant::now();

        // Emit initial 0% progress immediately
        if let Some(ref callback) = progress_callback {
            callback(0);
        }

        while let Some(chunk_result) = stream.next().await {
            // Check for cancellation before processing chunk
            {
                let cancel_flag = self.cancel_download_flag.read().await;
                if cancel_flag.as_ref() == Some(&model_name.to_string()) {
                    log::info!("Download cancelled for {}", model_name);
                    // Remove from active downloads on cancellation
                    let mut active = self.active_downloads.write().await;
                    active.remove(model_name);
                    return Err(anyhow!("Download cancelled by user"));
                }
            }

            let chunk = chunk_result
                .map_err(|e| anyhow!("Failed to read chunk: {}", e))?;

            file.write_all(&chunk).await
                .map_err(|e| anyhow!("Failed to write chunk to file: {}", e))?;

            downloaded += chunk.len() as u64;

            // Calculate progress
            let progress = if total_size > 0 {
                ((downloaded as f64 / total_size as f64) * 100.0) as u8
            } else {
                0
            };

View on GitHub (pinned to 0281737d87)

Solutions

  1. Treat this message as expected: catch it and show an informational 'Download cancelled' state, not an error
  2. To restart, call download_model again — note there is no byte-range resume, it restarts from 0
  3. Reset the model's progress state in the UI after cancellation so it shows as not-downloaded

Example fix

// before
try { await invoke('download_model', { modelName }); }
catch (e) { showError(e); } // shows 'cancelled' as a scary error

// after
try { await invoke('download_model', { modelName }); }
catch (e: any) {
  if (String(e).includes('cancelled by user')) setCancelledState();
  else showError(e);
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await invoke('download_model', { modelName });
} catch (e) {
  const msg = String(e);
  if (msg.includes('Download cancelled by user')) {
    setModelState(modelName, 'not-downloaded'); // expected flow, no error UI
  } else {
    showError(msg);
  }
}

Prevention

When it happens

Trigger: User clicks Cancel while the progress callback streams updates; a UI flow cancels a download to switch to a different model size mid-transfer.

Common situations: Normal UX cancellation; automated flows cancelling when a faster/quantized variant is preferred; test harnesses cancelling deliberately.

Related errors


AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16). Data as JSON: /api/errors/426c5175a42c323c. Report an issue: GitHub.