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
- Update the GPU driver - most device-lost-then-recovery-failed chains are driver bugs
- Check Windows Event Viewer (System log) at the crash time for Event 4101 / driver resets to identify the trigger
- Reduce GPU load and VRAM pressure (close GPU-heavy apps) to avoid TDR timeouts
- 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
- Keep GPU drivers current, especially on hybrid-graphics laptops
- Restart the app after GPU topology changes (docking, eGPU, driver installs) instead of assuming recovery
- Watch Event Viewer Event 4101 (TDR) on machines that hit this; fixing the TDR fixes the panic
- Reduce sustained GPU load so the driver never hits timeout thresholds
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
- Device lost: {err}
- Too many consecutive GPU errors. Last error: {error}
- Failed to find fxc.exe
- Error when registering clipboard format: {}
- RealtimeAudio priority should use spawn_realtime, not dispat
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/9811e23ec06228b1.
Report an issue: GitHub.