spacedriveapp/spacedrive · error
Stolen task channel closed
Error message
Stolen task channel closed
What it means
WorkStealer::steal ends by sending None ('nothing was stolen') back to the requesting worker's stole_task_tx and panics via .expect() if that channel is closed. The receiver, stole_task_rx, lives inside the requesting worker's merged message stream (run.rs:40-46); when that run future dies without aborting the detached steal task, the stream is dropped, the channel closes, and the terminal send at mod.rs:289-292 panics inside the spawned steal task.
Source
Thrown at crates/task-system/src/worker/mod.rs:292
.skip(stealer_id)
// Taking the total amount of workers
.take(total_workers)
// Removing the current worker as we can't steal from ourselves
.filter(|worker_comm| worker_comm.worker_id != stealer_id)
{
if worker_comm
.steal_task(stealer_id, stolen_task_tx.clone())
.await
{
trace!(stolen_worker_id = worker_comm.worker_id, "Stole a task");
return;
}
}
stolen_task_tx
.send(None)
.await
.expect("Stolen task channel closed");
}
}
View on GitHub (pinned to 6dfeccf211)
Solutions
- Library-level fix: make the terminal send non-fatal - let _ = stolen_task_tx.send(None).await; - a closed receiver means the requester is gone and the None signal is moot
- Library-level fix: abort the outstanding steal task on every exit path from run, not just NewTask/shutdown - e.g. a guard in run() (or Drop on Runner) that calls abort_steal_task(), or move current_steal_task_handle somewhere that survives into the respawn loop
- Fix the underlying worker panic that triggers the restart (see the 'Worker critically failed' log) - this error is a secondary symptom
- Keep runtime/task lifetimes stable so run futures are never dropped mid-sweep
Example fix
// before (worker/mod.rs:289-292)
stolen_task_tx
.send(None)
.await
.expect("Stolen task channel closed");
// after
if stolen_task_tx.send(None).await.is_err() {
trace!(stealer_id, "Requesting worker gone before 'no task stolen' signal; nothing to do");
} Defensive patterns
Strategy: fallback
Try / catch
// Panic fires in the detached WorkStealer::steal task; catch it with a hook:
std::panic::set_hook(Box::new(|info| {
let msg = info.to_string();
if msg.contains("Stolen task channel closed") {
// requester's run loop died mid-sweep; the None signal is moot
return;
}
eprintln!("panic: {msg}");
})); Prevention
- Eliminate worker panics: this only fires when a worker's run loop is dropped/restarted with an idle steal sweep still in flight (the guarded paths, NewTask and shutdown, already abort the steal task)
- Run with panic=unwind and fix every 'Worker critically failed and will restart' occurrence - each restart is a chance for this secondary panic
- Avoid dropping/cancelling the task system's tasks from outside; drive teardown exclusively through system.shutdown()
When it happens
Trigger: The requesting worker's run future panicking and the respawn loop restarting it (mod.rs:69-83): the old msg_stream holding stole_task_rx is dropped, but the steal task spawned at runner.rs:1402-1407 is only aborted via abort_steal_task() on the guarded paths (NewTask at run.rs:53 and shutdown at runner.rs:577) - the panic-restart path drops the Runner (which owns current_steal_task_handle) without aborting, so the detached steal task survives just long enough to panic on send(None). Also possible during runtime teardown.
Common situations: Any worker panic-restart while an idle steal sweep is in flight (steals fire every second per idle worker, runner.rs:917-929, so the overlap window is large in mostly-idle pools); production logs showing an stray panic from a detached task right after a 'Worker critically failed and will restart' line.
Related errors
- Worker channel closed trying to steal 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
- Worker channel closed trying to shutdown
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/ad575ee05faa8ede.
Report an issue: GitHub.