linebender/druid · warning

didn't get any modes

Error message

didn't get any modes

What it means

Thrown by the public util::refresh_rate helper when the X RandR reply contains an empty modes list for the requested output/crtc. Refresh rate is computed from the first display mode, so with no modes reported there is no rate to derive, and the function fails instead of returning a bogus value.

Solutions

  1. Fall back to a sensible default (e.g. 60.0) when refresh_rate returns Err, rather than propagating the failure.
  2. Query a connected/enabled output instead of the first output reported by RandR (filter RandR outputs with connection == Connected).
  3. Use a server with real mode data (Xorg with a real driver or Xvfb configured with a screen mode) for accurate rates.

Example fix

// before
let rate = refresh_rate(conn, screen_num)?;
// after
let rate = refresh_rate(conn, screen_num).unwrap_or(60.0);
Defensive patterns

Strategy: fallback

Validate before calling

let modes_len = conn.randr().get_screen_resources(screen.root)?.reply?.modes.len();
let has_modes = modes_len > 0;

Try / catch

let rate = match refresh_rate(&conn, screen_num) {
    Ok(r) => r,
    Err(_) => 60.0, // safe default when RandR reports no modes
};

Prevention

When it happens

Trigger: Calling refresh_rate on a system where the RandR GetMonitors/GetCrtcInfo reply has zero modes — disconnected or phantom outputs, headless servers (Xvfb has no RandR modes by default), or outputs attached to a disabled CRTC.

Common situations: Running inside Xvfb or a nested server without realistic mode data; laptops with a lid-closed/disabled external output queried for its refresh rate; broken driver setups where RandR reports outputs with no mode lines.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10). Data as JSON: /api/errors/567ffedaaf7a23a6. Report an issue: GitHub.

Appendix: source

Thrown at druid-shell/src/backend/x11/util.rs:28

use x11rb::errors::ReplyError;
use x11rb::protocol::randr::{ConnectionExt, ModeFlag};
use x11rb::protocol::render::{self, ConnectionExt as _};
use x11rb::protocol::xproto::{Screen, Visualid, Visualtype, Window};
use x11rb::xcb_ffi::XCBConnection;

// See: https://github.com/rtbo/rust-xcb/blob/master/examples/randr_screen_modes.rs
pub fn refresh_rate(conn: &Rc<XCBConnection>, window_id: Window) -> Option<f64> {
    let try_refresh_rate = || -> Result<f64, Error> {
        let reply = conn.randr_get_screen_resources(window_id)?.reply()?;

        // TODO(x11/render_improvements): Figure out a more correct way of getting the screen's refresh rate.
        //     Or maybe we don't even need this function if I figure out a better way to schedule redraws?
        //     Assuming the first mode is the one we want to use. This is probably a bug on some setups.
        //     Any better way to find the correct one?
        reply
            .modes
            .first()
            .ok_or_else(|| anyhow!("didn't get any modes"))
            .and_then(|mode_info| {
                let flags = mode_info.mode_flags;
                let vtotal = {
                    let mut val = mode_info.vtotal;
                    if (flags & u32::from(ModeFlag::DOUBLE_SCAN)) != 0 {
                        val *= 2;
                    }
                    if (flags & u32::from(ModeFlag::INTERLACE)) != 0 {
                        val /= 2;
                    }
                    val
                };

                if vtotal != 0 && mode_info.htotal != 0 {
                    Ok((mode_info.dot_clock as f64) / (vtotal as f64 * mode_info.htotal as f64))
                } else {
                    Err(anyhow!("got nonsensical mode values"))
                }

View on GitHub (pinned to 0f8b1195e4)