{"record":{"id":"bc939c1feda39de6","repo":"zed-industries/zed","slug":"validated-in-benchappcontext-build","errorCode":null,"errorMessage":"validated in BenchAppContext::build","messagePattern":"validated in BenchAppContext::build","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gpui/src/app/bench_context.rs","lineNumber":592,"sourceCode":"    }\n\n    /// Reads app state.\n    pub fn read<R>(&self, read: impl FnOnce(&App) -> R) -> R {\n        let app = self.app.borrow();\n        read(&app)\n    }\n\n    /// Runs queued foreground tasks on this thread and waits for in flight\n    /// background work to finish. Timers that aren't due yet are not waited\n    /// for (see [`ThreadedDispatcher::run_until_idle`]). Scheduled frames are\n    /// delivered after each task poll and when there are no ready tasks, but\n    /// animations alone do not keep this method running.\n    pub fn run_until_idle(&self) {\n        let dispatcher = self\n            .background_executor\n            .dispatcher()\n            .as_threaded()\n            .expect(\"validated in BenchAppContext::build\");\n        dispatcher.run_until_idle_with(|| {\n            let ran_tasks = dispatcher.run_ready_main_tasks_with(\n                || true,\n                || {\n                    self.dispatch_pending_frames(|| true);\n                },\n            );\n            if !ran_tasks {\n                self.dispatch_pending_frames(|| true);\n            }\n            ran_tasks\n        });\n    }\n\n    /// Alternates draining queued work with GPUI update cycles until neither\n    /// makes progress, so state dropped by benchmark code is fully released.\n    ///\n    /// Dropped entities are released only inside an update's effect flush, and","sourceCodeStart":574,"sourceCodeEnd":610,"githubUrl":"https://github.com/zed-industries/zed/blob/9d272b036335401f339d024ea94968fd51016c40/crates/gpui/src/app/bench_context.rs#L574-L610","documentation":"`BenchAppContext::run_until_idle` calls `background_executor.dispatcher().as_threaded().expect(\"validated in BenchAppContext::build\")`. This panics because the dispatcher behind the context's executors is not a `ThreadedDispatcher`. The library normally guarantees this in `BenchAppContext::build` (an assert on line 533 requires a platform constructed via `gpui::bench_platform`), so hitting the expect means the context was built against a non-threaded platform — typically the deterministic test platform used by `TestAppContext` — bypassing that validation.","triggerScenarios":"Calling `run_until_idle()` (directly or via `settle()`, `add_empty_window()`, or `teardown()`) on a `BenchAppContext` whose platform was not constructed with `gpui::bench_platform` — e.g. constructing the context with a `TestPlatform` backed by a deterministic/single-threaded dispatcher, or swapping the executor after build.","commonSituations":"Reusing a test harness's `TestPlatform` for a benchmark instead of calling `bench_platform`; wiring a custom `Platform` implementation whose `dispatcher()` returns a non-threaded dispatcher; copy-pasting `TestAppContext` setup code into a `#[gpui::bench]` benchmark.","solutions":["Construct the platform with `gpui::bench_platform(headless_renderer_factory, text_system)` so its executors are backed by a `ThreadedDispatcher`.","Ensure the `BenchAppContext` is created via its normal `build` constructor, which asserts the dispatcher is threaded (the panic message's 'validated in BenchAppContext::build' invariant).","If you are writing a plain unit test rather than a benchmark, use `TestAppContext`/`gpui::test` instead of `BenchAppContext`.","If a custom platform is required, implement `PlatformDispatcher::as_threaded` to return `Some(&ThreadedDispatcher)`."],"exampleFix":"// before\nlet platform = TestPlatform::new();\nlet cx = BenchAppContext::build(platform, ...);\ncx.run_until_idle(); // panics: not a ThreadedDispatcher\n\n// after\nlet platform = gpui::bench_platform(None, text_system);\nlet cx = BenchAppContext::build(platform, ...);\ncx.run_until_idle();","handlingStrategy":"validation","validationCode":"if cx.background_executor.dispatcher().as_threaded().is_none() {\n    panic!(\"BenchAppContext requires a platform built with gpui::bench_platform\");\n}","typeGuard":"fn is_bench_platform(executor: &BackgroundExecutor) -> bool {\n    executor.dispatcher().as_threaded().is_some()\n}","tryCatchPattern":null,"preventionTips":["Always build benchmark apps on gpui::bench_platform.","Never share a TestPlatform between #[gpui::test] tests and #[gpui::bench] benchmarks.","Check dispatcher().as_threaded().is_some() once at harness setup.","Use TestAppContext for unit tests instead of BenchAppContext."],"tags":["gpui","panics","dispatcher","benchmark"],"backgroundTag":"internal-invariant-violation","analyzedSha":"9d272b036335401f339d024ea94968fd51016c40","analyzedAt":"2026-09-12T19:35:53.743Z","contentChangedAt":"2026-09-12T19:35:53.743Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}