fix(trayicon): skip tray init on headless Linux/BSD instead of crashing#38
Merged
Conversation
pystray's _xorg backend opens an X11 connection at import time. On a
headless Linux box (server, SSH session without forwarding, container,
CI) this raises Xlib.error.DisplayNameError("") — not an ImportError —
so the existing except ImportError guard misses it and the daemon
fails to start.
- Short-circuit on Linux/BSD when neither DISPLAY nor WAYLAND_DISPLAY
is set: log "no display detected" and continue startup without the
tray icon.
- Broaden the import guard to Exception so any backend-init failure
(X11 connection refused, AppKit weirdness on macOS, future Wayland
backends) degrades to "tray unavailable" rather than crashing.
Fixes #34
Closed
This was referenced May 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #34. On a headless Linux box (server, SSH without X forwarding, container, CI), startup crashes with
Xlib.error.DisplayNameError: Bad display name ""and EpixNet refuses to run.Root cause
plugins/Trayicon/TrayiconPlugin.py:66importspystrayinside atry/except ImportError. On Linux, pystray's__init__.pyselects the_xorgbackend at import time, which callsXlib.display.Display(). With no$DISPLAYset, that raisesXlib.error.DisplayNameError— not anImportError— so the guard misses it and the unhandled exception abortsactions.main().The Trayicon plugin is
"default": "enabled"(plugin_info.json), so every headless Linux user hits this on first run.Fix
Two layers of defense in
TrayiconPlugin.py:DISPLAYnorWAYLAND_DISPLAYis set, log "no display detected" and continue startup without the tray icon. Avoids even attempting the import, so the user sees a clean message instead of a traceback.Exception(in addition toImportError) so backend-init failures from any platform (X11 connection refused, future Wayland backends, broken macOS AppKit) degrade gracefully to "tray unavailable" instead of crashing.super().main()is called in both branches, so the rest of EpixNet boots normally.Test plan
python3 -c "import ast; ast.parse(open('plugins/Trayicon/TrayiconPlugin.py').read())"— syntax OKunset DISPLAY && python3 epixnet.py— verify clean "no display detected" log and successful boot$DISPLAYset, verify tray icon still appearssys.platform)Workaround for affected users until merged
Rename
plugins/Trayicon→plugins/disabled-Trayiconto disable the plugin.