netbirdio/netbird · info
xembed: X error (ignored): %s (code=%d, request=%d.%d, resou
Error message
xembed: X error (ignored): %s (code=%d, request=%d.%d, resource=0x%lx)
What it means
Not a failure: a stderr diagnostic printed by the custom Xlib error handler installed for the Linux tray (client/ui/xembed_tray_linux.c). It replaces Xlib's default handler, which calls exit() on any asynchronous X error; returning 0 makes the error a logged no-op so one stray protocol error cannot kill the whole UI process. The message always includes '(ignored)'.
Source
Thrown at client/ui/xembed_tray_linux.c:29
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define SYSTEM_TRAY_REQUEST_DOCK 0
#define XEMBED_MAPPED (1 << 0)
/* Xlib's default protocol-error handler calls exit() on any async X error,
killing the whole UI process. Handlers are process-global (not
per-Display), so a single install covers our raw tray Display and GDK's.
Tray work is full of races the X server reports asynchronously — the tray
manager window dying between xembed_find_tray and xembed_dock (BadWindow
on XSendEvent), or x11_move_window touching a popup the WM already
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. */View on GitHub (pinned to 93e97f4bf1)
Solutions
- No action needed: the error was already swallowed by design; check whether the tray icon still functions
- If the tray icon vanished, restart the tray provider (extension/applet) or relaunch the UI so it re-docks
- Keep xembed_install_error_handlers installed; removing it restores Xlib's exit-on-error default and makes these races fatal
Defensive patterns
Strategy: fallback
Prevention
- Keep xembed_install_error_handlers() installed after every XOpenDisplay; it is idempotent and cheap
- Treat these lines as expected noise during tray-manager restarts; only investigate if the tray icon stops working
- Re-dock or relaunch the UI after the tray provider comes back instead of assuming UI failure
When it happens
Trigger: Asynchronous X errors from tray races the code comments name: the system-tray manager window dying between xembed_find_tray and xembed_dock (BadWindow on XSendEvent), or x11_move_window touching a popup the window manager already destroyed.
Common situations: GNOME/KDE tray extensions or systray daemons restarting while the NetBird UI runs; flaky StatusNotifier/XEmbed support on minimal window managers; the line appears in stderr but the tray and app keep working.
Related errors
- xembed: X I/O error (connection lost)
- 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/6c7857ca56d951cf.
Report an issue: GitHub.