{"record":{"id":"7afea1fd8526a126","repo":"linebender/druid","slug":"tried-to-build-a-window-without-setting-the-handle","errorCode":null,"errorMessage":"Tried to build a window without setting the handler","messagePattern":"Tried to build a window without setting the handler","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"druid-shell/src/backend/gtk/window.rs","lineNumber":280,"sourceCode":"        self.level = Some(level);\n    }\n\n    pub fn set_window_state(&mut self, state: window::WindowState) {\n        self.state = Some(state);\n    }\n\n    pub fn set_title(&mut self, title: impl Into<String>) {\n        self.title = title.into();\n    }\n\n    pub fn set_menu(&mut self, menu: Menu) {\n        self.menu = Some(menu);\n    }\n\n    pub fn build(self) -> Result<WindowHandle, ShellError> {\n        let handler = self\n            .handler\n            .expect(\"Tried to build a window without setting the handler\");\n\n        let window = ApplicationWindow::new(self.app.gtk_app());\n\n        window.set_title(&self.title);\n        window.set_resizable(self.resizable);\n        window.set_decorated(self.show_titlebar);\n        let mut transparent = false;\n        if self.transparent {\n            if let Some(screen) = gtk::prelude::GtkWindowExt::screen(&window) {\n                let visual = screen.rgba_visual();\n                transparent = visual.is_some();\n                window.set_visual(visual.as_ref());\n            }\n        }\n        window.set_app_paintable(transparent);\n\n        // Get the scale factor based on the GTK reported DPI\n        let scale_factor = window.display().default_screen().resolution() / SCALE_TARGET_DPI;","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/linebender/druid/blob/0f8b1195e4e073f9597f2865299c3d18f8e4005f/druid-shell/src/backend/gtk/window.rs#L262-L298","documentation":"WindowBuilder::build() on the GTK backend unwraps the handler field with expect: a window cannot be constructed without a WinHandler that receives its events. Forgetting to call set_handler before build causes this panic. The handler is what connects the raw GTK window to druid's event loop.","triggerScenarios":"Calling `WindowBuilder::new(app).build()` without a preceding `.set_handler(...)` on the builder; consuming the builder via a helper that resets or replaces the handler; constructing raw druid-shell windows in tests/tools without wiring a handler.","commonSituations":"Writing custom shells or test harnesses on top of druid-shell; example code stripped down and losing the set_handler call; building windows headlessly for screenshot testing.","solutions":["Call `.set_handler(Box::new(YourHandler::new()))` on the WindowBuilder before `.build()`.","If the handler type is conditionally created, ensure every branch assigns a handler before build.","Prefer build_native_window (higher-level path) which sets a handler for you.","Refactor so the builder is constructed together with its handler to prevent omission."],"exampleFix":"// before\nlet handle = WindowBuilder::new(app)\n    .set_title(\"Demo\")\n    .build()?;\n\n// after\nlet handle = WindowBuilder::new(app)\n    .set_title(\"Demo\")\n    .set_handler(Box::new(DemoHandler::new()))\n    .build()?;","handlingStrategy":"validation","validationCode":"// builder-shape guard: check handler presence in a wrapper\nstruct CheckedBuilder(WindowBuilder);\nimpl CheckedBuilder {\n    fn build(self) -> Result<WindowHandle, Error> {\n        self.0.set_handler(Box::new(DefaultHandler::default())).build()\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always chain .set_handler(...) immediately after WindowBuilder::new(...).","Centralize window creation in one function so the handler cannot be forgotten.","Prefer higher-level helpers (build_native_window) that set handlers automatically.","Exercise window construction in tests so the panic surfaces early."],"tags":["rust","gtk","window","panic","druid-shell","gui"],"backgroundTag":"missing-required-argument","analyzedSha":"0f8b1195e4e073f9597f2865299c3d18f8e4005f","analyzedAt":"2026-09-10T14:27:34.582Z","contentChangedAt":"2026-09-10T14:27:34.582Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}