{"record":{"id":"9f6d8653668b8aab","repo":"zed-industries/zed","slug":"realtimeaudio-priority-should-use-spawn-realtime-9f6d86","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_windows/src/dispatcher.rs","lineNumber":109,"sourceCode":"    #[inline(always)]\n    pub(crate) fn execute_runnable(runnable: RunnableVariant) {\n        let location = runnable.metadata().location;\n        let spawned = runnable.metadata().spawned;\n        gpui::profiler::update_running_task(spawned, location);\n        runnable.run();\n        gpui::profiler::save_task_timing();\n    }\n}\n\nimpl PlatformDispatcher for WindowsDispatcher {\n    fn is_main_thread(&self) -> bool {\n        current().id() == self.main_thread_id\n    }\n\n    fn dispatch(&self, runnable: RunnableVariant, priority: Priority) {\n        let priority = match priority {\n            Priority::RealtimeAudio => {\n                panic!(\"RealtimeAudio priority should use spawn_realtime, not dispatch\")\n            }\n            Priority::High => TP_CALLBACK_PRIORITY_HIGH,\n            Priority::Medium => TP_CALLBACK_PRIORITY_NORMAL,\n            Priority::Low => TP_CALLBACK_PRIORITY_LOW,\n        };\n        self.dispatch_on_threadpool(priority, runnable);\n    }\n\n    fn dispatch_on_main_thread(&self, runnable: RunnableVariant, priority: Priority) {\n        match self.main_sender.send(priority, runnable) {\n            Ok(_) => {\n                if !self.wake_posted.swap(true, Ordering::AcqRel) {\n                    unsafe {\n                        PostMessageW(\n                            Some(self.platform_window_handle.as_raw()),\n                            WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD,\n                            WPARAM(self.validation_number),\n                            LPARAM(0),","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/gpui_windows/src/dispatcher.rs#L91-L127","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Route real-time audio tasks through spawn_realtime (e.g. background_executor().spawn_realtime(...)) instead of spawn/dispatch with Priority::RealtimeAudio","If you cannot use spawn_realtime in that context, downgrade the priority to High so the generic dispatch path is legal","Audit call sites for tasks configured with RealtimeAudio that are handed to generic dispatch/spawn APIs","Check the gpui changelog/docs: the dispatch vs spawn_realtime split is a hard contract on Windows"],"exampleFix":"// before: panics on Windows - RealtimeAudio reaches generic dispatch\nlet task = TaskBuilder::new(audio_work).priority(Priority::RealtimeAudio);\ncx.background_executor().dispatch(task); // ends in WindowsDispatcher::dispatch\n\n// after: use the dedicated real-time spawn path\nlet task = TaskBuilder::new(audio_work).priority(Priority::RealtimeAudio);\ncx.background_executor().spawn_realtime(task);","handlingStrategy":"validation","validationCode":"// single scheduling helper that enforces the dispatch/spawn_realtime split\nfn schedule(executor: &BackgroundExecutor, priority: Priority, task: Task) {\n    if matches!(priority, Priority::RealtimeAudio) {\n        executor.spawn_realtime(task);\n    } else {\n        executor.spawn(task);\n    }\n}","typeGuard":"fn needs_realtime_pool(priority: Priority) -> bool {\n    matches!(priority, Priority::RealtimeAudio)\n}","tryCatchPattern":null,"preventionTips":["Treat RealtimeAudio as spawn_realtime-only by convention and encode it in one scheduling helper","Add a debug assertion in shared code that dispatch is never called with RealtimeAudio","Test audio paths on Windows specifically - it is the platform that enforces this invariant with a panic"],"tags":["windows","gpui","dispatcher","priority","realtime-audio"],"backgroundTag":"invalid-task-priority","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}