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

  1. Update Zed — dispatcher teardown ordering fixes land regularly; this panic is treated as an internal bug
  2. In app code, don't detach tasks that can outlive the app; store and drop them before quit
  3. Report with a backtrace and the exact quit sequence if reproducible
Defensive patterns

Strategy: validation

Prevention

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


AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20). Data as JSON: /api/errors/f8e005de34cd9a20. Report an issue: GitHub.