spacedriveapp/spacedrive · error
Interrupter ack channel closed
Error message
Interrupter ack channel closed
What it means
When a task finishes, Interrupter::drop calls close() (task.rs:289-312), which drains interruption requests that arrived after completion and acks each one; the .expect at task.rs:306 panics if the requester's ack receiver was already dropped. The requester is the detached future inside TaskWorktable::pause/suspend/cancel that is itself awaiting that ack. So this panic means the other half of a pause/suspend/cancel handshake was cancelled without completing: usually Tokio runtime teardown killing detached tasks mid-handshake, or a preceding panic in the chain (the drain task aborts on the first failed ack, stranding any later requests).
Source
Thrown at crates/task-system/src/task.rs:306
pub(super) fn close(&self) {
self.interrupt_rx.close();
if !self.interrupt_rx.is_empty() {
trace!("Pending interruption requests were not handled");
spawn({
let interrupt_rx = self.interrupt_rx.clone();
async move {
let mut interrupt_stream = pin!(interrupt_rx);
while let Some(InterruptionRequest { kind, ack }) =
interrupt_stream.next().await
{
trace!(
?kind,
"Interrupter received interruption request after task was completed"
);
ack.send(()).expect("Interrupter ack channel closed");
}
}
.in_current_span()
});
}
}
}
#[macro_export]
macro_rules! check_interruption {
($interrupter:ident) => {
let interrupter: &Interrupter = $interrupter;
match interrupter.try_check_interrupt() {
Some($crate::InterruptionKind::Cancel) => {
::tracing::trace!("Task was canceled by the user");
return Ok($crate::ExecStatus::Canceled);
}View on GitHub (pinned to 6dfeccf211)
Solutions
- Quiesce before teardown: let every pause/cancel/resume handshake complete before dropping the runtime
- Avoid requesting interruptions exactly at shutdown; cancel-on-drop wrappers firing during teardown are a classic trigger
- Library fix: replace ack.send(()).expect(...) with `if ack.send(()).is_err() { warn!(...) }` — the sibling path in InterrupterFuture::poll (task.rs:209-211) already warns instead of panicking
- When triaging, find the FIRST panic in the chain (RUST_LOG=task_system=trace); this one is usually a cascade, not the root
Example fix
// before (crates/task-system/src/task.rs, Interrupter::close drain task)
ack.send(()).expect("Interrupter ack channel closed");
// after: match the tolerant style already used in InterrupterFuture::poll (task.rs:209-211)
if ack.send(()).is_err() {
warn!(?kind, "Interrupter ack channel closed; requester went away during teardown");
} Defensive patterns
Strategy: validation
Validate before calling
// Let every interruption handshake finish before tearing down the runtime. // 1. stop issuing new pause/cancel/suspend calls shutting_down.store(true, Ordering::Release); // 2. await tasks to a quiesced state (handles resolved or paused and stable) let _ = join_all(live_handles).await; // 3. only then shutdown + runtime drop, so no drain-vs-requester race remains
Try / catch
Fires in a detached drain task; call-site catch_unwind cannot see it. Use a panic hook to log it and inspect the FIRST panic in the chain — this one is almost always downstream of another failure or runtime teardown.
Prevention
- Do not end a #[tokio::test] or drop a Runtime with pause/cancel requests in flight
- Avoid pause/cancel calls racing task completion at shutdown
- If maintaining a fork: make the drain ack tolerant (warn) like InterrupterFuture::poll already is
When it happens
Trigger: A pause/suspend/cancel request is queued just as the running task completes, and by the time close()'s drain task acks it, the worktable-side awaiting future was dropped (runtime shutdown killed it, or it already panicked at its own 'Task failed to ack ...' expect).
Common situations: Dropping a Runtime or ending a #[tokio::test] with a pause/cancel in flight; CancelTaskOnDrop firing during teardown; cascades that start with any other channel-closed expect in the task-system.
Related errors
- System channel closed trying to report working
- System channel closed trying to resume task
- Worker channel closed trying to pause a not running task
- Worker channel closed trying to cancel a not running task
- Worker channel closed trying to force task abortion
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/2162e932be2a500a.
Report an issue: GitHub.