emilk/egui · error

winit window doesn't exist

Error message

winit window doesn't exist

What it means

`GlowIntegration::window` calls `window_opt(viewport_id)` and unwraps the result with `expect("winit window doesn't exist")`. A viewport entry exists in `self.viewports`, but its `window: Option<Arc<Window>>` is `None`. The library assumes any viewport present in the map (other than transient states) has an associated winit window; `None` indicates the window was closed/destroyed without removing the viewport entry, or the viewport is still being initialized.

Source

Thrown at crates/eframe/src/native/glow_integration.rs:1417

        } else {
            log::debug!("context is already not current??? could be duplicate suspend event");
        }
        Ok(())
    }

    fn viewport(&self, viewport_id: ViewportId) -> &Viewport {
        self.viewports
            .get(&viewport_id)
            .expect("viewport doesn't exist")
    }

    fn window_opt(&self, viewport_id: ViewportId) -> Option<Arc<Window>> {
        self.viewport(viewport_id).window.clone()
    }

    fn window(&self, viewport_id: ViewportId) -> Arc<Window> {
        self.window_opt(viewport_id)
            .expect("winit window doesn't exist")
    }

    fn resize(&mut self, viewport_id: ViewportId, physical_size: winit::dpi::PhysicalSize<u32>) {
        let width_px = NonZeroU32::new(physical_size.width).unwrap_or(NonZeroU32::MIN);
        let height_px = NonZeroU32::new(physical_size.height).unwrap_or(NonZeroU32::MIN);

        if let Some(viewport) = self.viewports.get(&viewport_id)
            && let Some(gl_surface) = &viewport.gl_surface
        {
            change_gl_context(
                &mut self.current_gl_context,
                &mut self.not_current_gl_context,
                gl_surface,
            );
            gl_surface.resize(
                self.current_gl_context
                    .as_ref()
                    .expect("failed to get current context to resize surface"),

View on GitHub (pinned to 441971a776)

Solutions

  1. Prefer `window_opt` in your own integration code and handle the `None` case instead of the panicking `window` API.
  2. Ensure viewport removal happens in the same frame the window is destroyed so `viewports` never holds entries with `None` windows.
  3. Guard event handling against events for closed viewports (check the id before calling `window`).
  4. If reproducible, file an eframe issue with the event sequence; as a workaround disable viewports in `NativeOptions`.

Example fix

// before
let window = integration.window(viewport_id);
// after
if let Some(window) = integration.window_opt(viewport_id) {
    // use window
} else {
    log::warn!("window for {:?} already closed", viewport_id);
}
Defensive patterns

Strategy: validation

Validate before calling

// Prefer the fallible accessor before touching the window
if let Some(window) = runner.window_opt(viewport_id) {
    use_window(&window);
} else {
    eprintln!("viewport {:?} has no window; skipping", viewport_id);
}

Type guard

fn live_window(v: &Viewport) -> Option<Arc<Window>> { v.window.clone() }

Prevention

When it happens

Trigger: Calling `window(viewport_id)` for a viewport whose `window` field is `None` — typically during teardown, when the window was destroyed (e.g. `ViewportCommand::Close` processed) but the viewport record lingers, or when the id refers to a viewport mid-creation.

Common situations: Handling a winit event (resize, redraw, user-close) for a window that was just destroyed; deferred viewport code running after the parent closed the child window; race between close handling and the event loop delivering one more event for the dead id.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of emilk/egui@441971a776 (2026-09-12). Data as JSON: /api/errors/31764e7be434b7e6. Report an issue: GitHub.