linebender/druid · error
Tried to build a window without setting the handler
Error message
Tried to build a window without setting the handler
What it means
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.
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.
Example fix
// before
let handle = WindowBuilder::new(app)
.set_title("Demo")
.build()?;
// after
let handle = WindowBuilder::new(app)
.set_title("Demo")
.set_handler(Box::new(DemoHandler::new()))
.build()?; Defensive patterns
Strategy: validation
Validate before calling
// builder-shape guard: check handler presence in a wrapper
struct CheckedBuilder(WindowBuilder);
impl CheckedBuilder {
fn build(self) -> Result<WindowHandle, Error> {
self.0.set_handler(Box::new(DefaultHandler::default())).build()
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- There is no globally active Application
- TabsPolicy::Build called on a policy that does not support…
- commands should be dispatched via dispatch_cmd
- command must carry a ContextMenu .
- No path received for filename
AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10).
Data as JSON: /api/errors/7afea1fd8526a126.
Report an issue: GitHub.
Appendix: source
Thrown at druid-shell/src/backend/gtk/window.rs:280
self.level = Some(level);
}
pub fn set_window_state(&mut self, state: window::WindowState) {
self.state = Some(state);
}
pub fn set_title(&mut self, title: impl Into<String>) {
self.title = title.into();
}
pub fn set_menu(&mut self, menu: Menu) {
self.menu = Some(menu);
}
pub fn build(self) -> Result<WindowHandle, ShellError> {
let handler = self
.handler
.expect("Tried to build a window without setting the handler");
let window = ApplicationWindow::new(self.app.gtk_app());
window.set_title(&self.title);
window.set_resizable(self.resizable);
window.set_decorated(self.show_titlebar);
let mut transparent = false;
if self.transparent {
if let Some(screen) = gtk::prelude::GtkWindowExt::screen(&window) {
let visual = screen.rgba_visual();
transparent = visual.is_some();
window.set_visual(visual.as_ref());
}
}
window.set_app_paintable(transparent);
// Get the scale factor based on the GTK reported DPI
let scale_factor = window.display().default_screen().resolution() / SCALE_TARGET_DPI;View on GitHub (pinned to 0f8b1195e4)