Zackriya-Solutions/meetily · error · anyhow::Error
Download worker ended before completing cancellation cleanup
Error message
Download worker ended before completing cancellation cleanup
What it means
During cancel_download cleanup, the engine subscribes to the download worker's completion watch channel. If completion.changed() returns Err, it means the watch channel's sender was dropped — i.e., the download worker task terminated without ever setting the completion flag, so cancellation cleanup can never be confirmed.
Source
Thrown at frontend/src-tauri/src/parakeet_engine/parakeet_engine.rs:1220
&self,
model_name: &str,
cleanup_timeout: Duration,
) -> Result<CancelDownloadOutcome> {
let active_download = {
let active_downloads = self.active_downloads.lock().await;
let Some(active_download) = active_downloads.downloads.get(model_name).cloned() else {
return Ok(CancelDownloadOutcome::Cancelled);
};
active_download.cancellation.cancel();
active_download
};
let mut completion = active_download.completion.subscribe();
if !*completion.borrow() {
match timeout(cleanup_timeout, completion.changed()).await {
Ok(Ok(())) => {}
Ok(Err(_)) => {
return Err(anyhow!(
"Download worker ended before completing cancellation cleanup"
));
}
Err(_) => return Ok(CancelDownloadOutcome::Pending),
}
}
Ok(CancelDownloadOutcome::Cancelled)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crossbeam::queue::SegQueue;
use tempfile::tempdir;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpListener;View on GitHub (pinned to a2cb62e827)
Solutions
- Retry the cancel operation; if the outcome is still broken, restart the app to reset download worker state.
- Check Rust logs for a panic or abort in the download worker task to identify the root cause.
- Ensure the worker sets completion=true (or drops the sender only after setting it) in all exit paths, including error paths.
- Reduce race windows: only trigger cancel after the download has started reporting progress, or make the worker's completion channel a shutdown-safe signal.
Example fix
// before
Ok(Err(_)) => {
return Err(anyhow!("Download worker ended before completing cancellation cleanup"));
}
// after (treat closed channel as cleanup finished if the worker exited deliberately)
Ok(Err(_)) => {
if worker_join_handle.is_finished() {
return Ok(CancelDownloadOutcome::Cancelled);
}
return Err(anyhow!("Download worker ended before completing cancellation cleanup"));
} Defensive patterns
Strategy: try-catch
Validate before calling
// Before cancelling, check the worker is still alive
if worker_handle.is_finished() {
eprintln!("worker already exited; skip cleanup wait");
} Type guard
// Rust: check the watch channel is still connected before waiting
if active_download.completion.sender().is_some() {
// safe to await completion.changed()
} Try / catch
// Rust
match timeout(cleanup_timeout, completion.changed()).await {
Ok(Ok(())) => Ok(CancelDownloadOutcome::Cancelled),
Ok(Err(_)) => {
log::warn!("completion sender dropped; treating as worker exit");
Ok(CancelDownloadOutcome::Cancelled) // or surface to user with retry hint
}
Err(_) => Ok(CancelDownloadOutcome::Pending),
} Prevention
- Set the completion flag in every exit path of the download worker (success, error, panic hook).
- Wrap worker bodies with catch_unwind or spawn a supervision task to mark completion on panic.
- Drop the watch sender only after setting completion=true.
- Check Rust logs for worker panics/aborts when cancellation behaves unexpectedly.
When it happens
Trigger: In cancel_download, while waiting on active_download.completion.changed() within cleanup_timeout, the watch sender is dropped because the download worker task panicked, was aborted, or exited early without marking completion — the Ok(Err(_)) branch.
Common situations: The download worker panicked mid-download (e.g., a bug or OOM kill of the task); the task holding the watch sender was aborted after cancellation; the worker exited early on an unhandled error path without setting completion=true, leaving the cleanup watcher observing a closed channel.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Download cancelled by user
- Download worker ended before completing cancellation cleanup
- Download cancelled by user
- Download already in progress
- Failed to preserve {} during cancellation: {}
AI-assisted analysis of Zackriya-Solutions/meetily@a2cb62e827 (2026-09-12).
Data as JSON: /api/errors/674d328861e1df85.
Report an issue: GitHub.