{"record":{"id":"0ebf54624edb51e0","repo":"zed-industries/zed","slug":"realtimeaudio-priority-should-use-spawn-realtime","errorCode":null,"errorMessage":"RealtimeAudio priority should use spawn_realtime, not dispatch","messagePattern":"RealtimeAudio priority should use spawn_realtime, not dispatch","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gpui_macos/src/dispatcher.rs","lineNumber":44,"sourceCode":"\nimpl MacDispatcher {\n    pub fn new() -> Self {\n        Self\n    }\n}\n\nimpl PlatformDispatcher for MacDispatcher {\n    fn is_main_thread(&self) -> bool {\n        let is_main_thread: BOOL = unsafe { msg_send![class!(NSThread), isMainThread] };\n        is_main_thread == YES\n    }\n\n    fn dispatch(&self, runnable: RunnableVariant, priority: Priority) {\n        let context = runnable.into_raw().as_ptr() as *mut c_void;\n\n        let queue_priority = match priority {\n            Priority::RealtimeAudio => {\n                panic!(\"RealtimeAudio priority should use spawn_realtime, not dispatch\")\n            }\n            Priority::High => DispatchQueueGlobalPriority::High,\n            Priority::Medium => DispatchQueueGlobalPriority::Default,\n            Priority::Low => DispatchQueueGlobalPriority::Low,\n        };\n\n        unsafe {\n            DispatchQueue::global_queue(GlobalQueueIdentifier::Priority(queue_priority))\n                .exec_async_f(context, trampoline);\n        }\n    }\n\n    fn dispatch_on_main_thread(&self, runnable: RunnableVariant, _priority: Priority) {\n        let context = runnable.into_raw().as_ptr() as *mut c_void;\n        unsafe {\n            DispatchQueue::main().exec_async_f(context, trampoline);\n        }\n    }","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/zed-industries/zed/blob/9d272b036335401f339d024ea94968fd51016c40/crates/gpui_macos/src/dispatcher.rs#L26-L62","documentation":"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.","triggerScenarios":"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.","commonSituations":"Contributors adding audio-related tasks and reusing dispatch with the realtime priority; refactors that move spawn_realtime work into plain dispatch calls.","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"],"exampleFix":"// before\ndispatcher.dispatch(runnable, Priority::RealtimeAudio); // panic on macOS\n\n// after\ndispatcher.spawn_realtime(async move { /* audio work */ });","handlingStrategy":"validation","validationCode":"if let Priority::RealtimeAudio = priority {\n    dispatcher.spawn_realtime(fut); // correct path for realtime audio\n} else {\n    dispatcher.dispatch(runnable, priority);\n}","typeGuard":"fn is_dispatchable_priority(priority: Priority) -> bool {\n    !matches!(priority, Priority::RealtimeAudio)\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["zed","gpui","macos","dispatcher","priority","api-misuse","panic"],"backgroundTag":"dispatcher-api-misuse","analyzedSha":"9d272b036335401f339d024ea94968fd51016c40","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}