linebender/druid · error
Invalid screen num
Error message
Invalid screen num: {} What it means
Thrown by Application::new in the X11 backend when the supplied screen_num index does not exist in the X server's list of screens (connection.setup().roots). The X server exposes one root screen per configured monitor/seat, and this index must point at one of them. The library throws instead of silently defaulting to screen 0 because running on the wrong screen would create windows on the wrong root.
Solutions
- Pass 0 (or None to use the default screen from DISPLAY) as screen_num unless you know the server has multiple screens.
- Query the valid range first: connection.setup().roots.len() and clamp/validate the index before calling Application::new.
- Check how Xvfb/Xorg was started; launch with the right number of screens (e.g. Xvfb :1 -screen 0 ...) or fix the DISPLAY environment variable.
Example fix
// before let app = Application::new(None, 1)?; // fails on single-screen servers // after let app = Application::new(None, 0)?; // default screen from DISPLAY
Defensive patterns
Strategy: validation
Validate before calling
// before Application::new
let conn = x11rb::connect(None).map(|(c, s)| (c, s))?.0;
let screen_count = conn.setup().roots.len();
assert!(screen_num < screen_count, "screen {} out of 0..{}", screen_num, screen_count); Prevention
- Prefer passing None so the default screen from DISPLAY is used.
- Never hardcode screen indices; derive them from the connection setup.
- In CI, start Xvfb with an explicit, known screen configuration.
When it happens
Trigger: Calling druid_shell::backend::x11::Application::new(None, screen_num) with a screen_num >= connection.setup().roots.len(), e.g. hardcoded 1 on a single-screen X server, or a value obtained from DISPLAY parsing when the X server was restarted with fewer screens.
Common situations: Hardcoded screen indices in CI containers or headless setups (Xvfb started without +extension or with only :0.0); DISPLAY strings like :0.1 that no longer match the server config after a display-manager restart; code copied from multi-monitor setups run on single-screen machines.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- invalid screen num
- Couldn't get visual from screen
- No window with id
- didn't get any modes
- Failed to update cairo drawable
AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10).
Data as JSON: /api/errors/0752fd8171969f6a.
Report an issue: GitHub.
Appendix: source
Thrown at druid-shell/src/backend/x11/application.rs:301
text: load_cursor("text"),
pointer: load_cursor("pointer"),
crosshair: load_cursor("crosshair"),
not_allowed: load_cursor("not-allowed"),
row_resize: load_cursor("row-resize"),
col_resize: load_cursor("col-resize"),
};
let atoms = Rc::new(
AppAtoms::new(&*connection)?
.reply()
.context("get X11 atoms")?,
);
let screen = connection
.setup()
.roots
.get(screen_num)
.ok_or_else(|| anyhow!("Invalid screen num: {}", screen_num))?;
let root_visual_type = util::get_visual_from_screen(screen)
.ok_or_else(|| anyhow!("Couldn't get visual from screen"))?;
let argb_visual_type = util::get_argb_visual_type(&connection, screen)?;
let timestamp = Rc::new(Cell::new(x11rb::CURRENT_TIME));
let pending_events = Default::default();
let clipboard = Clipboard::new(
Rc::clone(&connection),
screen_num,
Rc::clone(&atoms),
atoms.CLIPBOARD,
Rc::clone(&pending_events),
Rc::clone(×tamp),
);
let primary = Clipboard::new(
Rc::clone(&connection),
screen_num,
Rc::clone(&atoms),View on GitHub (pinned to 0f8b1195e4)