spacedriveapp/spacedrive · error
System channel closed trying to resume not running task
Error message
System channel closed trying to resume not running task
What it means
In dispatch_resume_not_running_task_request, after the worker replies, the system forwards the result on the caller's oneshot ack channel. ack.send fails (and the spawned task panics) when the requesting side already dropped its receiver, i.e. the caller of resume went away before the answer arrived. The task-system treats these channels as infallible invariants, so a broken invariant aborts the dispatch task and the resume result is lost.
Source
Thrown at crates/task-system/src/system.rs:286
let first_attempt_worker_id = task_work_table.worker_id();
workers[first_attempt_worker_id]
.resume_task(task_id, tx)
.await;
let res = rx
.await
.expect("Task system channel closed trying to resume not running task");
if matches!(res, Err(SystemError::TaskNotFound(_))) {
warn!(
%first_attempt_worker_id,
"Failed the first try to resume a not running task, trying again",
);
workers[task_work_table.worker_id()]
.resume_task(task_id, ack)
.await;
} else {
ack.send(res)
.expect("System channel closed trying to resume not running task");
}
}
}
.in_current_span(),
);
trace!("Task system resumed task");
}
#[instrument(skip(workers, ack, task_work_table))]
fn dispatch_pause_not_running_task_request<E: RunError>(
workers: &Arc<Vec<Worker<E>>>,
task_id: TaskId,
task_work_table: Arc<TaskWorktable>,
ack: oneshot::Sender<Result<(), SystemError>>,
) {
spawn(
{
let workers: Arc<Vec<Worker<E>>> = Arc::clone(workers);View on GitHub (pinned to 6dfeccf211)
Solutions
- Check whether the panic occurs only during shutdown/disconnect races: then the lost ack is benign and the caller is already gone
- Find code that drops task-control futures early (timeout wrappers, abort handles) and keep them alive until the ack resolves
- Patch the task-system to replace these expects with logged send failures: a dead ack receiver is recoverable, not fatal
- Look for a preceding worker panic in the logs: worker death cascades into broken channel invariants
Example fix
// before: expect panics the dispatch task when the caller is gone
ack.send(res).expect("System channel closed trying to resume not running task");
// after: a dropped requester is not fatal
if ack.send(res).is_err() {
warn!(%task_id, "Resume ack receiver dropped; caller went away");
} Defensive patterns
Strategy: validation
Validate before calling
// Keep the requesting future alive until the ack arrives; never wrap task control in timeouts let ack_rx = system.resume(task_id); // returns the oneshot receiver let res = ack_rx.await; // hold this to completion — dropping early closes the channel assert!(matches!(res, Ok(_)), "resume must get its ack");
Prevention
- Never abort or timeout task-control futures before their ack resolves
- Treat 'System channel closed' panics as caller-lifecycle bugs, not worker bugs
- Patch consumers of task-system to await acks in the same scope that issues requests
When it happens
Trigger: The caller wrapped resume in a timeout/abort and dropped the future before the ack arrived; client disconnects right after requesting resume of a not-running task; shutdown racing an in-flight resume request.
Common situations: UI request with a short timeout cancelling as the system is mid-dispatch; daemon shutdown while task control requests are pending.
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/30a032d7da61f370.
Report an issue: GitHub.