zed-industries/zed · critical

Device lost: {err}

Error message

Device lost: {err}

What it means

When Direct3D reports the GPU device was removed or reset, the Windows event handler asks the renderer to recreate its DirectX device and dependent state via handle_device_lost. If that recovery fails and returns Err, the handler panics with the recovery error. So the panic means not just 'the driver reset the GPU' but 'GPUI could not rebuild its device afterwards' - typically the adapter is gone or keeps failing.

Source

Thrown at crates/gpui_windows/src/events.rs:1263

    }

    fn handle_window_visibility_changed(&self, handle: HWND, wparam: WPARAM) -> Option<isize> {
        if wparam.0 == 1 {
            self.draw_window(handle, false);
        }
        None
    }

    fn handle_device_lost(&self, lparam: LPARAM) -> Option<isize> {
        let devices = lparam.0 as *const DirectXDevices;
        let devices = unsafe { &*devices };
        if let Err(err) = self
            .state
            .renderer
            .borrow_mut()
            .handle_device_lost(&devices)
        {
            panic!("Device lost: {err}");
        }
        // Make sure the first `draw_window` after recovery (whether it comes
        // from the forced WM_GPUI_FORCE_UPDATE_WINDOW or a stray WM_PAINT in
        // between) is treated as a forced render so it both clears
        // `skip_draws` and bypasses the view cache.
        self.state.force_render_pending.set(true);
        Some(0)
    }

    fn handle_dm_pointer_hit_test(&self, wparam: WPARAM) -> Option<isize> {
        self.state.direct_manipulation.on_pointer_hit_test(wparam);
        None
    }

    #[inline]
    fn draw_window(&self, handle: HWND, force_render: bool) -> Option<isize> {
        let Some(_guard) = self.state.draw_coordinator.try_begin_draw() else {
            log::debug!("deferring re-entrant draw of window {handle:?}");

View on GitHub (pinned to f4178619ac)

Solutions

  1. Update the GPU driver - most device-lost-then-recovery-failed chains are driver bugs
  2. Check Windows Event Viewer (System log) at the crash time for Event 4101 / driver resets to identify the trigger
  3. Reduce GPU load and VRAM pressure (close GPU-heavy apps) to avoid TDR timeouts
  4. If TDRs recur, extend the TdrDelay registry value or remove overclocks; otherwise report upstream with the err text from the panic
Defensive patterns

Strategy: fallback

Try / catch

// run the window/message loop under a supervisor and relaunch after GPU loss
loop {
    let ok = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| run_gpui_window()));
    if ok.is_ok() {
        break;
    }
    std::thread::sleep(std::time::Duration::from_secs(2)); // let the driver settle before retry
}

Prevention

When it happens

Trigger: A device-lost window message arrives (driver timeout/TDR, docking/undocking a hybrid-graphics laptop, driver upgrade while the app runs, VRAM exhaustion) and the subsequent device/swapchain recreation inside handle_device_lost fails, propagating Err into the panic.

Common situations: Windows TDR events visible in Event Viewer as 'Display driver ... stopped responding and has successfully recovered' (Event 4101); eGPU hot-docking; driver upgrades forcing device removal; factory-overclocked GPUs failing under load.

Related errors


AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20). Data as JSON: /api/errors/9811e23ec06228b1. Report an issue: GitHub.