zed-industries/zed · error
blocking sender returned without value
Error message
blocking sender returned without value
What it means
LinuxDispatcher::dispatch sends a runnable over a channel to the background executor. The send can only fail when the receiving side has been dropped, which happens while the dispatcher is being destroyed during app teardown; in that case it panics 'blocking sender returned without value'. The sibling dispatch_on_main_thread tolerates failure (main thread gone implies shutdown), so this panic indicates a task dispatched after the background executor was torn down.
Source
Thrown at crates/gpui_linux/src/linux/dispatcher.rs:110
Self {
main_sender,
timer_sender,
background_sender,
_background_threads: background_threads,
main_thread_id: thread::current().id(),
}
}
}
impl PlatformDispatcher for LinuxDispatcher {
fn is_main_thread(&self) -> bool {
thread::current().id() == self.main_thread_id
}
fn dispatch(&self, runnable: RunnableVariant, priority: Priority) {
self.background_sender
.send(priority, runnable)
.unwrap_or_else(|_| panic!("blocking sender returned without value"));
}
fn dispatch_on_main_thread(&self, runnable: RunnableVariant, priority: Priority) {
self.main_sender
.send(priority, runnable)
.unwrap_or_else(|runnable| {
// NOTE: Runnable may wrap a Future that is !Send.
//
// This is usually safe because we only poll it on the main thread.
// However if the send fails, we know that:
// 1. main_receiver has been dropped (which implies the app is shutting down)
// 2. we are on a background thread.
// It is not safe to drop something !Send on the wrong thread, and
// the app will exit soon anyway, so we must forget the runnable.
std::mem::forget(runnable);
});
}
View on GitHub (pinned to f4178619ac)
Solutions
- Update Zed — dispatcher teardown ordering fixes land regularly; this panic is treated as an internal bug
- In app code, don't detach tasks that can outlive the app; store and drop them before quit
- Report with a backtrace and the exact quit sequence if reproducible
Defensive patterns
Strategy: validation
Prevention
- Don't detach background tasks that can outlive the app; keep Task handles and drop them before quit
- Check dispatcher liveness / app state before dispatching from long-lived background threads during shutdown
- Update Zed — dispatcher teardown ordering is fixed upstream when reports come in
When it happens
Trigger: Any code on any thread calling dispatcher.dispatch after the GPUI app has begun quitting and the background receiver was dropped — typically detached tasks waking up during shutdown.
Common situations: Shutdown races in gpui_linux: background work spawned by GPUI or app code that outlives the dispatcher; late completion of I/O tasks during quit.
Related errors
- main thread message channel should not be closed yet, extens
- wl_seat below required version: {} < {}
- wl_output below required version: {} < {}
- `{}` must be a positive normal number or `randr`. Got `{}`
- `{}` must be a positive number or `randr`. Got `{}`
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/f8e005de34cd9a20.
Report an issue: GitHub.