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
- Ensure gtk::init() (or gtk::Application startup) has completed successfully before any icon loading is triggered
- 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)
- Verify GTK libraries and an icon theme are actually installed (e.g. adwaita-icon-theme / breeze-icon-theme, and xdg-utils data dirs)
- Replace the expect() with graceful handling: match on gtk::IconTheme::default() and log/return None so the tray degrades instead of panicking
- 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
- Always run gtk::init() before any IconTheme access and check its Result
- Initialize the notifier host only after the GTK main loop/display is up
- Keep icon loading on the GTK main thread or dispatch via a MainContext
- In tests, run under xvfb-run or a mock icon loader
- Never .expect()/unwrap() on Option-returning GTK getters in host code
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
- no pixbuf from theme.load_icon despite no error
- Error opening log file
- Error, trying to add multiple children to a…
- could not get default display
- OneToNElementsMap got into inconsistent state
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)