tonhowtf/omniget · info
Send cancelled while paused
Error message
Send cancelled while paused
What it means
While the session is paused (session.paused is true), run_sender sleeps in 100ms intervals and re-checks cancel each tick; if the token fires during the pause, it bails with "Send cancelled while paused". Distinguishes cancellation-while-paused from cancellation-during-transfer for clearer UI state.
Solutions
- Expected control flow — handle it as a cancellation and clear both paused and cancel state on the session.
- If surprising, check whether the UI auto-cancels sessions paused beyond a threshold.
- On catch, close the relay connection so the blocked receiver doesn't wait forever.
Example fix
// before
// cancel during pause reported as generic failure
if let Err(e) = run_sender(session).await { return Err(e); }
// after
if let Err(e) = run_sender(session).await {
if e.to_string().contains("cancelled while paused") {
session.paused.store(false, std::sync::atomic::Ordering::Relaxed);
ui.mark_cancelled(&session.id);
} else { return Err(e); }
} Defensive patterns
Strategy: try-catch
Validate before calling
if cancel.is_cancelled() && session.paused.load(std::sync::atomic::Ordering::Relaxed) {
anyhow::bail!("Cannot pause: session already cancelled");
} Try / catch
match run_sender(session.clone(), cancel.clone()).await {
Err(e) if e.to_string().contains("cancelled while paused") => {
session.paused.store(false, std::sync::atomic::Ordering::Relaxed);
session.status.lock().await = "cancelled".into();
}
other => other?,
} Prevention
- Auto-cancel only paused sessions after a user-visible timeout.
- Clear the paused flag whenever the session is cancelled or dropped.
- Distinguish pause/cancel buttons clearly in the UI to avoid accidental cancels.
- Close the relay socket on cancel so the receiver doesn't hang on its read.
When it happens
Trigger: User pauses the transfer (setting session.paused) and then cancels; the next 100ms poll observes is_cancelled() inside the pause spin-loop.
Common situations: User pauses, changes their mind, and hits cancel; UI cancels long-paused sessions after a timeout; app shutdown while a transfer sits paused.
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
- Download cancelled
- Send cancelled while waiting for receiver
- Send cancelled while waiting for OK
- Send cancelled during transfer
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/3248bb6b3a97543d.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/src/platforms/p2p/mod.rs:321
tracing::info!(
"[p2p] transferring: {} ({} bytes)",
session.file_name,
session.file_size
);
let mut file = File::open(&session.file_path).await?;
let mut buf = vec![0u8; CHUNK_SIZE];
let mut sent: u64 = 0;
loop {
if cancel.is_cancelled() {
anyhow::bail!("Send cancelled during transfer");
}
while session.paused.load(std::sync::atomic::Ordering::Relaxed) {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
if cancel.is_cancelled() {
anyhow::bail!("Send cancelled while paused");
}
}
let n = file.read(&mut buf).await?;
if n == 0 {
break;
}
write_half.write_all(&buf[..n]).await?;
sent += n as u64;
*session.sent_bytes.lock().await = sent;
if session.file_size > 0 {
*session.progress.lock().await = (sent as f64 / session.file_size as f64) * 100.0;
}
}
write_half.flush().await?;View on GitHub (pinned to 8600b91f42)