zed-industries/zed · error

RealtimeAudio priority should use spawn_realtime, not dispat

Error message

RealtimeAudio priority should use spawn_realtime, not dispatch

What it means

The Windows dispatcher maps GPUI task priorities onto Windows thread-pool callback priorities, and RealtimeAudio is deliberately excluded: real-time audio tasks must go to the dedicated real-time path via spawn_realtime so they get the audio thread and its priority handling. If any code routes a RealtimeAudio-priority runnable through the generic dispatch(), the dispatcher panics immediately to surface the API misuse.

Source

Thrown at crates/gpui_windows/src/dispatcher.rs:109

    #[inline(always)]
    pub(crate) fn execute_runnable(runnable: RunnableVariant) {
        let location = runnable.metadata().location;
        let spawned = runnable.metadata().spawned;
        gpui::profiler::update_running_task(spawned, location);
        runnable.run();
        gpui::profiler::save_task_timing();
    }
}

impl PlatformDispatcher for WindowsDispatcher {
    fn is_main_thread(&self) -> bool {
        current().id() == self.main_thread_id
    }

    fn dispatch(&self, runnable: RunnableVariant, priority: Priority) {
        let priority = match priority {
            Priority::RealtimeAudio => {
                panic!("RealtimeAudio priority should use spawn_realtime, not dispatch")
            }
            Priority::High => TP_CALLBACK_PRIORITY_HIGH,
            Priority::Medium => TP_CALLBACK_PRIORITY_NORMAL,
            Priority::Low => TP_CALLBACK_PRIORITY_LOW,
        };
        self.dispatch_on_threadpool(priority, runnable);
    }

    fn dispatch_on_main_thread(&self, runnable: RunnableVariant, priority: Priority) {
        match self.main_sender.send(priority, runnable) {
            Ok(_) => {
                if !self.wake_posted.swap(true, Ordering::AcqRel) {
                    unsafe {
                        PostMessageW(
                            Some(self.platform_window_handle.as_raw()),
                            WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD,
                            WPARAM(self.validation_number),
                            LPARAM(0),

View on GitHub (pinned to f4178619ac)

Solutions

  1. Route real-time audio tasks through spawn_realtime (e.g. background_executor().spawn_realtime(...)) instead of spawn/dispatch with Priority::RealtimeAudio
  2. If you cannot use spawn_realtime in that context, downgrade the priority to High so the generic dispatch path is legal
  3. Audit call sites for tasks configured with RealtimeAudio that are handed to generic dispatch/spawn APIs
  4. Check the gpui changelog/docs: the dispatch vs spawn_realtime split is a hard contract on Windows

Example fix

// before: panics on Windows - RealtimeAudio reaches generic dispatch
let task = TaskBuilder::new(audio_work).priority(Priority::RealtimeAudio);
cx.background_executor().dispatch(task); // ends in WindowsDispatcher::dispatch

// after: use the dedicated real-time spawn path
let task = TaskBuilder::new(audio_work).priority(Priority::RealtimeAudio);
cx.background_executor().spawn_realtime(task);
Defensive patterns

Strategy: validation

Validate before calling

// single scheduling helper that enforces the dispatch/spawn_realtime split
fn schedule(executor: &BackgroundExecutor, priority: Priority, task: Task) {
    if matches!(priority, Priority::RealtimeAudio) {
        executor.spawn_realtime(task);
    } else {
        executor.spawn(task);
    }
}

Type guard

fn needs_realtime_pool(priority: Priority) -> bool {
    matches!(priority, Priority::RealtimeAudio)
}

Prevention

When it happens

Trigger: Calling executor.dispatch(runnable, Priority::RealtimeAudio) directly, or building a task with RealtimeAudio priority and spawning it through a path that ends in WindowsDispatcher::dispatch instead of spawn_realtime (custom spawners, ported extension code, code written against a platform that does not enforce the split).

Common situations: App or extension authors adding audio work who copy the generic background-spawn pattern but set Priority::RealtimeAudio; refactors that change which spawn function a task flows through; porting code between platforms where only Windows enforces the contract.

Related errors


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