emilk/egui · error

Failed to get display handle

Error message

Failed to get display handle

What it means

While building glutin `SurfaceAttributes`, eframe calls `window.window_handle()` (raw-window-handle's `HasWindowHandle`) and unwraps it with `.expect("Failed to get display handle")`. Note the message is misleading: it fetches the window handle (not the display handle), and panics if the platform backend cannot produce one for the newly created window.

Source

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

                Some(window.scale_factor() as f32),
                event_loop.system_theme(),
                self.max_texture_side,
            )
        });

        if viewport.gl_surface.is_none() {
            log::debug!("Creating a gl_surface for viewport {viewport_id:?}");

            // surface attributes
            let (width_px, height_px): (u32, u32) = window.inner_size().into();
            let width_px = NonZeroU32::new(width_px).unwrap_or(NonZeroU32::MIN);
            let height_px = NonZeroU32::new(height_px).unwrap_or(NonZeroU32::MIN);
            let surface_attributes = {
                glutin::surface::SurfaceAttributesBuilder::<glutin::surface::WindowSurface>::new()
                    .build(
                        window
                            .window_handle()
                            .expect("Failed to get display handle")
                            .as_raw(),
                        width_px,
                        height_px,
                    )
            };

            log::trace!("creating surface with attributes: {surface_attributes:?}");
            let gl_surface = unsafe {
                self.gl_config
                    .display()
                    .create_window_surface(&self.gl_config, &surface_attributes)?
            };

            log::trace!("surface created successfully: {gl_surface:?}. making context current");

            let not_current_gl_context =
                if let Some(not_current_context) = self.not_current_gl_context.take() {
                    not_current_context

View on GitHub (pinned to 441971a776)

Solutions

  1. Ensure a functional display server is available (valid DISPLAY or WAYLAND_DISPLAY); in CI use Xvfb or run software rendering (LIBGL_ALWAYS_SOFTWARE=1).
  2. Align versions of eframe, egui-winit, glutin, and raw-window-handle (same trait major versions).
  3. Avoid closing/destroying viewports concurrently with surface creation; keep viewport teardown on the same event-loop thread.
  4. If maintaining a fork, use `window_handle().ok()` and return a graceful `Result` error instead of `.expect`.
Defensive patterns

Strategy: validation

Validate before calling

// preflight display-server check before starting the eframe app
fn can_create_surfaces() -> bool {
    cfg!(target_os = "windows")
        || cfg!(target_os = "macos")
        || std::env::var_os("WAYLAND_DISPLAY").is_some()
        || std::env::var_os("DISPLAY").is_some()
}

Try / catch

// internal .expect panic: cannot catch; validate environment first and fail fast
if !can_create_surfaces() {
    eprintln!("No display server; cannot create GL surfaces");
    std::process::exit(1);
}

Prevention

When it happens

Trigger: Surface creation for a viewport whose window cannot yield a raw window handle — window already destroyed, unsupported backend, or platform handle conversion failure on X11/Wayland/Win32.

Common situations: Wayland/X11 sessions in containers or nested compositors; drivers/backends reporting windows without exportable handles; eframe/egui-winit/raw-window-handle version mismatches; closing a viewport while its surface is being created.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


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