{"record":{"id":"1a96232d2a4995ba","repo":"elkowar/eww","slug":"could-not-get-default-gtk-theme","errorCode":null,"errorMessage":"Could not get default gtk theme","messagePattern":"Could not get default gtk theme","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/notifier_host/src/icon.rs","lineNumber":32,"sourceCode":"    LoadIconFromFile {\n        path: String,\n        #[source]\n        source: gtk::glib::Error,\n    },\n    #[error(\"loading icon {icon_name:?} from theme {}\", .theme_path.as_ref().unwrap_or(&\"(default)\".to_owned()))]\n    LoadIconFromTheme {\n        icon_name: String,\n        theme_path: Option<String>,\n        #[source]\n        source: gtk::glib::Error,\n    },\n    #[error(\"no icon available\")]\n    NotAvailable,\n}\n\n/// Get the fallback GTK icon, as a final fallback if the tray item has no icon.\nasync fn fallback_icon(size: i32, scale: i32) -> Option<gtk::gdk_pixbuf::Pixbuf> {\n    let theme = gtk::IconTheme::default().expect(\"Could not get default gtk theme\");\n    match theme.load_icon_for_scale(\"image-missing\", size, scale, gtk::IconLookupFlags::FORCE_SIZE) {\n        Ok(pb) => pb,\n        Err(e) => {\n            log::error!(\"failed to load \\\"image-missing\\\" from default theme: {}\", e);\n            None\n        }\n    }\n}\n\n/// Load a pixbuf from StatusNotifierItem's [Icon format].\n///\n/// [Icon format]: https://freedesktop.org/wiki/Specifications/StatusNotifierItem/Icons/\nfn icon_from_pixmap(width: i32, height: i32, mut data: Vec<u8>) -> gtk::gdk_pixbuf::Pixbuf {\n    // We need to convert data from ARGB32 to RGBA32, since that's the only one that gdk-pixbuf\n    // understands.\n    for chunk in data.chunks_exact_mut(4) {\n        let a = chunk[0];\n        let r = chunk[1];","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/elkowar/eww/blob/48f5aa8b379adf29da0b0bb9ca04164f65d8bdaa/crates/notifier_host/src/icon.rs#L14-L50","documentation":"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.","triggerScenarios":"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).","commonSituations":"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).","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"],"exampleFix":"// before\nlet theme = gtk::IconTheme::default().expect(\"Could not get default gtk theme\");\n// after\nlet theme = match gtk::IconTheme::default() {\n    Some(t) => t,\n    None => {\n        log::error!(\"no default gtk icon theme (GTK not initialized or no display)\");\n        return None;\n    }\n};","handlingStrategy":"try-catch","validationCode":"// Rust: cannot catch panics idiomatically pre-call; guard instead\nfn ensure_gtk_ready() -> bool {\n    gtk::is_initialized_main_thread() && std::env::var(\"DISPLAY\").or_else(|_| std::env::var(\"WAYLAND_DISPLAY\")).is_ok()\n}","typeGuard":"fn default_theme() -> Option<gtk::IconTheme> {\n    if !gtk::is_initialized() { return None; }\n    gtk::IconTheme::default()\n}","tryCatchPattern":"// Prefer avoiding the panic; if unavoidable, isolate the call\nlet theme = std::panic::catch_unwind(|| gtk::IconTheme::default())\n    .ok()\n    .flatten()\n    .ok_or_else(|| { log::error!(\"no default gtk theme\"); None })?;","preventionTips":["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"],"tags":["gtk","rust","panic","icon-theme","display","initialization"],"backgroundTag":"missing-env-var","analyzedSha":"48f5aa8b379adf29da0b0bb9ca04164f65d8bdaa","analyzedAt":"2026-09-08T03:13:26.897Z","contentChangedAt":"2026-09-08T03:13:26.897Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}