DioxusLabs/dioxus · error
tray icon builder failed
Error message
tray icon builder failed
What it means
init_tray_icon builds the OS tray icon with tray-icon's TrayIconBuilder and unwraps the Result. On Linux the tray depends on the StatusNotifierItem protocol over dbus; on other desktops it depends on system APIs. When creation fails (no tray service reachable, wrong environment) the app panics at startup. Icon decoding errors are tolerated - only builder failure is fatal.
Source
Thrown at packages/desktop/src/trayicon.rs:45
#[allow(unused)]
pub fn init_tray_icon(menu: DioxusTrayMenu, icon: Option<DioxusTrayIcon>) -> DioxusTray {
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
{
let icon = icon.map(Ok).unwrap_or_else(crate::default_icon);
let tray = tray_icon::TrayIconBuilder::new()
.with_menu(Box::new(menu))
.with_menu_on_left_click(false);
let tray = match icon {
Ok(icon) => tray.with_icon(icon),
Err(err) => {
tracing::trace!("No tray icon: {:?}", err);
tray
}
};
provide_context(tray.build().expect("tray icon builder failed"))
}
}
/// Returns a default tray icon menu
pub fn default_tray_icon() -> DioxusTrayMenu {
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
{
use tray_icon::menu::{Menu, PredefinedMenuItem};
let tray_menu = Menu::new();
tray_menu
.append_items(&[&PredefinedMenuItem::quit(None)])
.unwrap();
tray_menu
}
}
/// Provides a hook to the tray icon
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]View on GitHub (pinned to 393d190a80)
Solutions
- Run the app inside a desktop session with a working tray (KDE, GNOME plus AppIndicator/Tray Icons extension, or a standalone tray)
- Make the tray optional: only call init_tray_icon behind a CLI flag or runtime environment check
- Elsewhere, use the safe hook use_tray_icon() -> Option<TrayIcon> so absence is handled gracefully
- As a last resort wrap the init call in std::panic::catch_unwind so a tray-less environment does not kill the app
Example fix
// before
init_tray_icon(default_tray_icon(), None);
// after
use dioxus_desktop::tao::platform::unix::...
let tray_ok = std::panic::catch_unwind(|| init_tray_icon(default_tray_icon(), None)).is_ok();
if !tray_ok { tracing::warn!("system tray unavailable; continuing without it"); } Defensive patterns
Strategy: fallback
Validate before calling
// Only create the tray when a desktop session plausibly has one
fn tray_probably_available() -> bool {
#[cfg(target_os = "linux")]
{
std::env::var("XDG_CURRENT_DESKTOP").is_ok() && std::env::var("DISPLAY").is_ok()
}
#[cfg(not(target_os = "linux"))]
{ true }
} Try / catch
// Keep the app alive when the environment has no tray
let tray = std::panic::catch_unwind(|| {
init_tray_icon(default_tray_icon(), None)
});
if tray.is_err() { tracing::warn!("no system tray; running without tray icon"); } Prevention
- Make the tray opt-in via a CLI flag or setting instead of unconditional at startup
- Consume use_tray_icon() -> Option<TrayIcon> so UI degrades gracefully without a tray
- On GNOME install an AppIndicator/Tray Icons extension; test on KDE or a standalone tray before shipping
When it happens
Trigger: Calling init_tray_icon on a Linux session without a system tray (bare window manager, GNOME without an AppIndicator extension, headless/WSL sessions) or in an environment where the tray backend cannot initialize.
Common situations: Developing or CI-running a tray-enabled desktop app headlessly; distros without an SNI provider installed; GNOME default session which ships no tray.
Related errors
- expected URL to be UTF-8 encoded
- Head element to exist
- Body element to exist
- Failed to get asset manager
- Failed to get asset manager as object
AI-assisted analysis of DioxusLabs/dioxus@393d190a80 (2026-08-16).
Data as JSON: /api/errors/c41adba795153cc3.
Report an issue: GitHub.