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
- Fall back to a sensible default (e.g. 60.0) when refresh_rate returns Err, rather than propagating the failure.
- Query a connected/enabled output instead of the first output reported by RandR (filter RandR outputs with connection == Connected).
- 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
- Only query refresh rate for outputs with an active CRTC/connected state.
- Default to 60 Hz (or an app-configured value) when rate detection fails.
- In headless/CI environments, don't rely on RandR-derived rates at all.
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
- Invalid screen num
- Couldn't get visual from screen
- invalid screen num
- No window with id
- Failed to update cairo drawable
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)