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
MacDispatcher::dispatch maps GPUI Priority to libdispatch global queue priorities; RealtimeAudio has no global-queue equivalent — realtime audio work must run on a dedicated realtime thread via the spawn_realtime APIs. Calling dispatch with Priority::RealtimeAudio is a programming error and panics immediately with that instruction.
Source
Thrown at crates/gpui_macos/src/dispatcher.rs:44
impl MacDispatcher {
pub fn new() -> Self {
Self
}
}
impl PlatformDispatcher for MacDispatcher {
fn is_main_thread(&self) -> bool {
let is_main_thread: BOOL = unsafe { msg_send![class!(NSThread), isMainThread] };
is_main_thread == YES
}
fn dispatch(&self, runnable: RunnableVariant, priority: Priority) {
let context = runnable.into_raw().as_ptr() as *mut c_void;
let queue_priority = match priority {
Priority::RealtimeAudio => {
panic!("RealtimeAudio priority should use spawn_realtime, not dispatch")
}
Priority::High => DispatchQueueGlobalPriority::High,
Priority::Medium => DispatchQueueGlobalPriority::Default,
Priority::Low => DispatchQueueGlobalPriority::Low,
};
unsafe {
DispatchQueue::global_queue(GlobalQueueIdentifier::Priority(queue_priority))
.exec_async_f(context, trampoline);
}
}
fn dispatch_on_main_thread(&self, runnable: RunnableVariant, _priority: Priority) {
let context = runnable.into_raw().as_ptr() as *mut c_void;
unsafe {
DispatchQueue::main().exec_async_f(context, trampoline);
}
}View on GitHub (pinned to 9d272b0363)
Solutions
- Use the realtime spawn APIs (PlatformDispatcher::spawn_realtime) for RealtimeAudio-priority work instead of dispatch
- If the work is not truly realtime audio, use Priority::High which maps to a libdispatch high-priority global queue
- Audit any code path that constructs Priority values dynamically before dispatching
Example fix
// before
dispatcher.dispatch(runnable, Priority::RealtimeAudio); // panic on macOS
// after
dispatcher.spawn_realtime(async move { /* audio work */ }); Defensive patterns
Strategy: validation
Validate before calling
if let Priority::RealtimeAudio = priority {
dispatcher.spawn_realtime(fut); // correct path for realtime audio
} else {
dispatcher.dispatch(runnable, priority);
} Type guard
fn is_dispatchable_priority(priority: Priority) -> bool {
!matches!(priority, Priority::RealtimeAudio)
} Prevention
- Reserve Priority::RealtimeAudio for spawn_realtime exclusively; treat dispatch with it as a compile-time-style mistake
- Use Priority::High for anything that is not true realtime audio work
- When porting dispatcher code between platforms, re-check each priority's supported entry point
When it happens
Trigger: Calling `dispatcher.dispatch(runnable, Priority::RealtimeAudio)` in GPUI code on macOS — typically new code choosing the wrong priority, or code ported from a platform whose dispatcher accepted it.
Common situations: Contributors adding audio-related tasks and reusing dispatch with the realtime priority; refactors that move spawn_realtime work into plain dispatch calls.
Related errors
- blocking sender returned without value
- Failed to get active display list. Result: {result}
- RealtimeAudio priority should use spawn_realtime, not dispat
- Expected to render a table row
- compute_indents_fn is required for UniformListDecoration
AI-assisted analysis of zed-industries/zed@9d272b0363 (2026-08-20).
Data as JSON: /api/errors/0ebf54624edb51e0.
Report an issue: GitHub.