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

  1. Expected control flow — handle it as a cancellation and clear both paused and cancel state on the session.
  2. If surprising, check whether the UI auto-cancels sessions paused beyond a threshold.
  3. 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

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


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)