You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
On Linux with no StatusNotifier host (GNOME without AppIndicator, or no session bus) the tray runs invisibly with no message, despite the documented console fallback #71
README's "Load-bearing behaviour" section says the console fallback covers "a DISPLAY pointing at nothing, a missing libX11, or no status-notifier host", and the comment on TrayAppBuilder.RecoverFromTrayFailure (TrayApp/TrayAppBuilder.cs, around L651-655) says the same. But when no org.kde.StatusNotifierWatcher is on the bus, Avalonia's DBusTrayIconImpl doesn't throw. It waits for one to appear. So StartWithClassicDesktopLifetime runs normally, HasStarted becomes true, and the tool sits there with no icon, no menu and no output. The only way out is Ctrl+C or kill. The same thing happens when there is no D-Bus session bus at all, where an icon can never appear.
Scenario
Run a TrayApp tool on stock GNOME (no AppIndicator extension), or from an X or ssh -X session with no DBUS_SESSION_BUS_ADDRESS. DesktopSession.IsAvailable returns true because DISPLAY is set, so the tool takes the tray path. OnStart runs (for NoSleep, that takes the inhibitor), nothing appears anywhere, and nothing is printed. --status meanwhile reports Tray icon: available (DISPLAY or WAYLAND_DISPLAY is set).
Reproduced at 3ef4d9e with the demo under Xvfb and TRAYAPP_DEBUG=1:
dbus-run-session -- sh -c 'xvfb-run -a dotnet ktsu.TrayApp.Demo.dll & sleep 12; ps ...'
# still alive after 12 s, stdout/stderr empty, tray.json written (OnStart ran)
env -u DBUS_SESSION_BUS_ADDRESS xvfb-run -a dotnet ktsu.TrayApp.Demo.dll
# silent until killed by timeout (exit 124), no fallback message
As a control, starting a watcher 8 s after the tool still registers the item (org.kde.StatusNotifierItem-<pid>-0). A host that arrives late is a real case, for example a login autostart racing the panel, so falling back to the console immediately would be wrong.
Suggested fix and acceptance criteria
On Linux, check the session bus before or just after starting the tray: is org.kde.StatusNotifierWatcher owned, and is IsStatusNotifierHostRegistered true? Tmds.DBus.Protocol is already in the dependency graph through Avalonia.FreeDesktop, but KTSU0006 means it needs a direct reference.
No session bus at all (no address and no $XDG_RUNTIME_DIR/bus): treat this like the other "no tray possible" cases. Print the existing "could not show a tray icon … Staying in the terminal instead." message and use the console runner, or have DesktopSession.IsAvailable return false.
Bus present but no watcher or host: write a stderr notice such as <tool>: no system tray (StatusNotifier host) is running; the icon will appear when one starts. Use --no-tray to run in the terminal. Optionally fall back after a grace period, but not immediately, so autostart keeps working.
--status / DesktopSession.Explanation tells apart "DISPLAY set, StatusNotifier host registered" and "DISPLAY set but no StatusNotifier host / no session bus".
The README row and the RecoverFromTrayFailure comment stop claiming that a missing host leads to a fallback.
Priority: High. Stock GNOME is the most common Linux desktop, and on it a TrayApp tool runs with no icon, no menu and no output. The only way out is Ctrl+C or kill. OnStart still runs, so a tool such as NoSleep holds its inhibitor where the user can't see it. --status also reports that the tray is available, and the README promises a fallback. Together these make the problem hard to diagnose.
Area / suggested assignment: Linux desktop detection in DesktopSession.IsAvailable/Explanation and TrayAppBuilder.RecoverFromTrayFailure, plus the README's "Load-bearing behaviour" row. This needs a direct Tmds.DBus.Protocol reference, because KTSU0006 flags the transitive one.
Next step: Handle the no-session-bus case first. It is unambiguous: fall back to the console runner with the existing message. Then add the stderr notice for a bus with no watcher or host, without an immediate fallback, so a late-starting panel still works. Update --status and the README in the same change.
Activity
matt-edmondson commentedon Nov 2, 2026
Triage
kill.OnStartstill runs, so a tool such as NoSleep holds its inhibitor where the user can't see it.--statusalso reports that the tray is available, and the README promises a fallback. Together these make the problem hard to diagnose.DesktopSession.IsAvailable/ExplanationandTrayAppBuilder.RecoverFromTrayFailure, plus the README's "Load-bearing behaviour" row. This needs a directTmds.DBus.Protocolreference, because KTSU0006 flags the transitive one.--statusand the README in the same change.Generated by Claude Code