netbirdio/netbird · error
xembed: X I/O error (connection lost)
Error message
xembed: X I/O error (connection lost)
What it means
stderr line from xembed_x_io_error_handler: the process-global I/O error handler fires when the X connection itself is lost (server gone, socket closed). Xlib treats an I/O error as fatal and exits the process even if the handler returns, so this handler can only log a clearer line than Xlib's default before the unavoidable exit.
Source
Thrown at client/ui/xembed_tray_linux.c:42
destroyed — and the default handler would take us down for any of them.
Returning 0 here makes the error a logged no-op instead. */
static int xembed_x_error_handler(Display *dpy, XErrorEvent *ev) {
char buf[256];
XGetErrorText(dpy, ev->error_code, buf, sizeof(buf));
fprintf(stderr,
"xembed: X error (ignored): %s (code=%d, request=%d.%d, resource=0x%lx)\n",
buf, ev->error_code, ev->request_code, ev->minor_code,
ev->resourceid);
return 0;
}
/* The I/O error handler fires when the X connection itself drops (server
gone, socket closed). Xlib treats this as fatal and exits even if we
return, so this can't keep the process alive — it only logs a clearer
line than Xlib's terse default before the unavoidable exit. */
static int xembed_x_io_error_handler(Display *dpy) {
(void)dpy;
fprintf(stderr, "xembed: X I/O error (connection lost)\n");
return 0;
}
/* Install the process-global handlers. Idempotent and cheap, so callers may
invoke it after every XOpenDisplay without tracking prior installs. */
void xembed_install_error_handlers(void) {
XSetErrorHandler(xembed_x_error_handler);
XSetIOErrorHandler(xembed_x_io_error_handler);
}
Window xembed_find_tray(Display *dpy, int screen) {
char atom_name[64];
snprintf(atom_name, sizeof(atom_name), "_NET_SYSTEM_TRAY_S%d", screen);
Atom sel = XInternAtom(dpy, atom_name, False);
return XGetSelectionOwner(dpy, sel);
}
int xembed_get_icon_size(Display *dpy, Window tray_mgr) {View on GitHub (pinned to 93e97f4bf1)
Solutions
- Nothing prevents the exit from inside the handler by design; run the UI under a supervisor (systemd --user, desktop session) that restarts it
- Persist any UI state outside the X event loop so an X-disconnect exit loses nothing
- If this happens mid-session on Wayland, check whether XWayland crashed (journalctl) rather than suspecting the NetBird UI
Defensive patterns
Strategy: fallback
Prevention
- Run the UI under a supervisor (systemd --user or the desktop session) so it restarts after the fatal X disconnect
- Persist state outside the X event loop; the process exits by design when the connection drops
- On Wayland, ensure XWayland stays available for as long as the tray is needed; check journalctl if it disappears mid-session
When it happens
Trigger: Logging out or shutting down/restarting the X server while the tray is connected; XWayland terminating when the Wayland session ends; a dropped 'ssh -X' forwarded session; an X server crash.
Common situations: Session teardown on Linux desktops; the UI running under a remote or virtual X display that disappears; Wayland sessions where XWayland stops unexpectedly.
Related errors
- xembed: X error (ignored): %s (code=%d, request=%d.%d, resou
- add IP to ipset: %w
- create ipset: %w
- failed to check rule: %w
- rule already exists
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/1892410a90dd8208.
Report an issue: GitHub.