elkowar/eww · error

Could not get default gtk theme

Error message

Could not get default gtk theme

What it means

This panic comes from an .expect() on gtk::IconTheme::default(), which returns an Option. GTK returns None when no default IconTheme can be created for the default screen/display — almost always because GTK has not been initialized (gtk::init() not yet called or failed) or there is no available display/theme lookup context. In fallback_icon this expect() runs while trying to load the 'image-missing' placeholder icon as a last-resort tray icon.

Solutions

  1. Ensure gtk::init() (or gtk::Application startup) has completed successfully before any icon loading is triggered
  2. Check that a display server is reachable: DISPLAY or WAYLAND_DISPLAY is set and the compositor/X server is up (e.g. run under a real session or use xvfb-run in tests)
  3. Verify GTK libraries and an icon theme are actually installed (e.g. adwaita-icon-theme / breeze-icon-theme, and xdg-utils data dirs)
  4. Replace the expect() with graceful handling: match on gtk::IconTheme::default() and log/return None so the tray degrades instead of panicking
  5. If loading on another thread, route icon work through the GTK main thread / main context

Example fix

// before
let theme = gtk::IconTheme::default().expect("Could not get default gtk theme");
// after
let theme = match gtk::IconTheme::default() {
    Some(t) => t,
    None => {
        log::error!("no default gtk icon theme (GTK not initialized or no display)");
        return None;
    }
};
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: cannot catch panics idiomatically pre-call; guard instead
fn ensure_gtk_ready() -> bool {
    gtk::is_initialized_main_thread() && std::env::var("DISPLAY").or_else(|_| std::env::var("WAYLAND_DISPLAY")).is_ok()
}

Type guard

fn default_theme() -> Option<gtk::IconTheme> {
    if !gtk::is_initialized() { return None; }
    gtk::IconTheme::default()
}

Try / catch

// Prefer avoiding the panic; if unavoidable, isolate the call
let theme = std::panic::catch_unwind(|| gtk::IconTheme::default())
    .ok()
    .flatten()
    .ok_or_else(|| { log::error!("no default gtk theme"); None })?;

Prevention

When it happens

Trigger: Calling load_icon_from_sni -> fallback_icon before gtk::init() has run, after gtk::init() failed, in a thread without a GTK main context/display, or in an environment where GTK cannot determine a default screen (headless / no X or Wayland display / missing icon theme infrastructure).

Common situations: Running the tray host on a headless CI box or over SSH without DISPLAY/WAYLAND_DISPLAY set; initializing the notifier host before the GTK main loop setup; spawning icon loading on a non-main thread before GTK is ready; broken or missing GTK/XDG icon-theme configuration (e.g. no xdg data dirs installed).

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of elkowar/eww@48f5aa8b37 (2026-09-08). Data as JSON: /api/errors/1a96232d2a4995ba. Report an issue: GitHub.

Appendix: source

Thrown at crates/notifier_host/src/icon.rs:32

    LoadIconFromFile {
        path: String,
        #[source]
        source: gtk::glib::Error,
    },
    #[error("loading icon {icon_name:?} from theme {}", .theme_path.as_ref().unwrap_or(&"(default)".to_owned()))]
    LoadIconFromTheme {
        icon_name: String,
        theme_path: Option<String>,
        #[source]
        source: gtk::glib::Error,
    },
    #[error("no icon available")]
    NotAvailable,
}

/// Get the fallback GTK icon, as a final fallback if the tray item has no icon.
async fn fallback_icon(size: i32, scale: i32) -> Option<gtk::gdk_pixbuf::Pixbuf> {
    let theme = gtk::IconTheme::default().expect("Could not get default gtk theme");
    match theme.load_icon_for_scale("image-missing", size, scale, gtk::IconLookupFlags::FORCE_SIZE) {
        Ok(pb) => pb,
        Err(e) => {
            log::error!("failed to load \"image-missing\" from default theme: {}", e);
            None
        }
    }
}

/// Load a pixbuf from StatusNotifierItem's [Icon format].
///
/// [Icon format]: https://freedesktop.org/wiki/Specifications/StatusNotifierItem/Icons/
fn icon_from_pixmap(width: i32, height: i32, mut data: Vec<u8>) -> gtk::gdk_pixbuf::Pixbuf {
    // We need to convert data from ARGB32 to RGBA32, since that's the only one that gdk-pixbuf
    // understands.
    for chunk in data.chunks_exact_mut(4) {
        let a = chunk[0];
        let r = chunk[1];

View on GitHub (pinned to 48f5aa8b37)