linebender/druid · error
Failed to create cairo surface
Error message
Failed to create cairo surface: {} What it means
Error in create_cairo_surface (x11 window build path): XCBSurface::create failed to wrap the XCB window drawable in a cairo XCB surface, and the cairo Status is formatted into the message. It fires when the cairo/xcb connection, drawable, or visual type is invalid — e.g. unsupported visual, connection creation failure, or cairo rejecting the XCB setup — and is called from build.
Solutions
- Verify the visual type obtained for the window is supported (24-bit/32-bit truecolor) before creating the surface
- Check that the XCB connection was successfully converted to a cairo connection
- Re-create the surface after the window/visual is fully initialized; log the cairo Status for the exact failure
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at druid-shell/src/backend/x11/window.rs:212 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10).
Data as JSON: /api/errors/1005a43747f772de.
Report an issue: GitHub.
Appendix: source
Thrown at druid-shell/src/backend/x11/window.rs:212
CairoXCBConnection::from_raw_none(
conn.get_raw_xcb_connection() as *mut cairo::ffi::xcb_connection_t
)
};
let cairo_drawable = XCBDrawable(window_id);
let mut xcb_visual = xcb_visualtype_t::from(*visual_type);
let cairo_visual_type = unsafe {
XCBVisualType::from_raw_none(
&mut xcb_visual as *mut xcb_visualtype_t as *mut cairo::ffi::xcb_visualtype_t,
)
};
let cairo_surface = XCBSurface::create(
&cairo_xcb_connection,
&cairo_drawable,
&cairo_visual_type,
self.size.width as i32,
self.size.height as i32,
)
.map_err(|status| anyhow!("Failed to create cairo surface: {}", status))?;
Ok(cairo_surface)
}
// TODO(x11/menus): make menus if requested
pub fn build(self) -> Result<WindowHandle, Error> {
let conn = self.app.connection();
let screen_num = self.app.screen_num();
let id = conn.generate_id()?;
let setup = conn.setup();
let env_dpi = std::env::var("DRUID_X11_DPI")
.ok()
.map(|x| x.parse::<f64>());
let scale = match env_dpi.or_else(|| self.app.rdb.get_value("Xft.dpi", "").transpose()) {
Some(Ok(dpi)) => {
let scale = dpi / 96.;
Scale::new(scale, scale)View on GitHub (pinned to 0f8b1195e4)