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

  1. Call `.set_handler(Box::new(YourHandler::new()))` on the WindowBuilder before `.build()`.
  2. If the handler type is conditionally created, ensure every branch assigns a handler before build.
  3. Prefer build_native_window (higher-level path) which sets a handler for you.
  4. 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

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


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)