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

  1. Pass 0 (or None to use the default screen from DISPLAY) as screen_num unless you know the server has multiple screens.
  2. Query the valid range first: connection.setup().roots.len() and clamp/validate the index before calling Application::new.
  3. 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

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


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(&timestamp),
        );
        let primary = Clipboard::new(
            Rc::clone(&connection),
            screen_num,
            Rc::clone(&atoms),

View on GitHub (pinned to 0f8b1195e4)