zed-industries/zed · critical
Failed to get active display list. Result: {result}
Error message
Failed to get active display list. Result: {result} What it means
On macOS, GPUI enumerates connected monitors by calling the CoreGraphics function CGGetActiveDisplayList into a fixed 32-entry buffer. If CoreGraphics returns any non-zero CGError code, gpui_macos panics because it cannot build the display list the platform needs. The panic fires inside the API that lists displays, typically during application startup or while reacting to a screen reconfiguration.
Source
Thrown at crates/gpui_macos/src/display.rs:63
}
/// Obtains an iterator over all currently active system displays.
pub fn all() -> impl Iterator<Item = Self> {
unsafe {
// We're assuming there aren't more than 32 displays connected to the system.
let mut displays = Vec::with_capacity(32);
let mut display_count = 0;
let result = CGGetActiveDisplayList(
displays.capacity() as u32,
displays.as_mut_ptr(),
&mut display_count,
);
if result == 0 {
displays.set_len(display_count as usize);
displays.into_iter().map(MacDisplay)
} else {
panic!("Failed to get active display list. Result: {result}");
}
}
}
}
#[link(name = "ApplicationServices", kind = "framework")]
unsafe extern "C" {
fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef;
}
impl PlatformDisplay for MacDisplay {
fn id(&self) -> DisplayId {
DisplayId::new(self.0 as u64)
}
fn uuid(&self) -> Result<Uuid> {
let cfuuid = unsafe { CGDisplayCreateUUIDFromDisplayID(self.0 as CGDirectDisplayID) };
anyhow::ensure!(View on GitHub (pinned to f4178619ac)
Solutions
- Run the app from a normal GUI login session (WindowServer reachable), not a bare SSH or CI shell on macOS
- Retry launching after the display change settles: unplug/replug external monitors, or reboot to reset CoreGraphics state
- If it repeats, reproduce with a tiny program calling CGGetActiveDisplayList and capture the returned CGError code, then report it upstream with that code
- If you maintain gpui_macos, replace the panic with logging plus an empty iterator (or a Result) so callers can degrade gracefully
Example fix
// before (crates/gpui_macos/src/display.rs)
if result == 0 {
displays.set_len(display_count as usize);
displays.into_iter().map(MacDisplay)
} else {
panic!("Failed to get active display list. Result: {result}");
}
// after: log and degrade instead of killing the process
if result == 0 {
displays.set_len(display_count as usize);
displays.into_iter().map(MacDisplay)
} else {
log::error!("CGGetActiveDisplayList failed with {result}; continuing with no displays");
Vec::new().into_iter().map(MacDisplay)
} Defensive patterns
Strategy: validation
Validate before calling
// probe CoreGraphics before initializing gpui on macOS
use core_graphics::display::CGDisplay;
fn displays_available() -> bool {
CGDisplay::active_displays()
.map(|displays| !displays.is_empty())
.unwrap_or(false)
}
if !displays_available() {
eprintln!("no displays via CoreGraphics; run inside a GUI session");
std::process::exit(1);
} Try / catch
// convert the startup panic into a diagnosable skip (CI/headless runs)
let boot = std::panic::catch_unwind(|| {
// gpui Application::new().run(...) path that lists displays
});
if boot.is_err() {
eprintln!("display initialization failed; aborting");
} Prevention
- Launch GPUI apps from a GUI login session, never a bare SSH shell on macOS
- Wrap application bootstrap in catch_unwind in CI so display panics become skipped runs, not red herring crashes
- Avoid launching during display reconfiguration (wake from sleep, docking); retry after a short delay
When it happens
Trigger: Calling gpui's display enumeration (the platform API backed by this code in crates/gpui_macos/src/display.rs, e.g. all_displays()) when CGGetActiveDisplayList returns a CGError: no WindowServer connection (headless SSH/CI session), a display reconfiguration in progress (plug/unplug, sleep/wake, GPU switching), or more active displays than the pre-allocated 32-slot buffer.
Common situations: Running a GPUI-based app over SSH or in CI on macOS where the WindowServer is unreachable; launching exactly while macOS switches GPUs or renegotiates displays after wake; kiosk or virtual-display setups with a very large display count.
Related errors
- RealtimeAudio priority should use spawn_realtime, not dispat
- database not initialized
- blocking sender returned without value
- Too many consecutive GPU errors. Last error: {error}
- Expected to render a table row
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/2b2fb2f241b00a83.
Report an issue: GitHub.