{"record":{"id":"1892410a90dd8208","repo":"netbirdio/netbird","slug":"xembed-x-i-o-error-connection-lost","errorCode":null,"errorMessage":"xembed: X I/O error (connection lost)\n","messagePattern":"xembed: X I/O error \\(connection lost\\)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/ui/xembed_tray_linux.c","lineNumber":42,"sourceCode":"   destroyed — and the default handler would take us down for any of them.\n   Returning 0 here makes the error a logged no-op instead. */\nstatic int xembed_x_error_handler(Display *dpy, XErrorEvent *ev) {\n    char buf[256];\n    XGetErrorText(dpy, ev->error_code, buf, sizeof(buf));\n    fprintf(stderr,\n            \"xembed: X error (ignored): %s (code=%d, request=%d.%d, resource=0x%lx)\\n\",\n            buf, ev->error_code, ev->request_code, ev->minor_code,\n            ev->resourceid);\n    return 0;\n}\n\n/* The I/O error handler fires when the X connection itself drops (server\n   gone, socket closed). Xlib treats this as fatal and exits even if we\n   return, so this can't keep the process alive — it only logs a clearer\n   line than Xlib's terse default before the unavoidable exit. */\nstatic int xembed_x_io_error_handler(Display *dpy) {\n    (void)dpy;\n    fprintf(stderr, \"xembed: X I/O error (connection lost)\\n\");\n    return 0;\n}\n\n/* Install the process-global handlers. Idempotent and cheap, so callers may\n   invoke it after every XOpenDisplay without tracking prior installs. */\nvoid xembed_install_error_handlers(void) {\n    XSetErrorHandler(xembed_x_error_handler);\n    XSetIOErrorHandler(xembed_x_io_error_handler);\n}\n\nWindow xembed_find_tray(Display *dpy, int screen) {\n    char atom_name[64];\n    snprintf(atom_name, sizeof(atom_name), \"_NET_SYSTEM_TRAY_S%d\", screen);\n    Atom sel = XInternAtom(dpy, atom_name, False);\n    return XGetSelectionOwner(dpy, sel);\n}\n\nint xembed_get_icon_size(Display *dpy, Window tray_mgr) {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/ui/xembed_tray_linux.c#L24-L60","documentation":"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.","triggerScenarios":"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.","commonSituations":"Session teardown on Linux desktops; the UI running under a remote or virtual X display that disappears; Wayland sessions where XWayland stops unexpectedly.","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"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["x11","xlib","connection-lost","linux","c"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}