java-native-access/jna · error · X11Exception

Cannot send <msg> event.

Error message

Cannot send <msg> event.

What it means

Window.sendEvent wraps XSendEvent: when the call returns 0 (failure) instead of non-zero, the method throws "Cannot send <msg> event." where <msg> is a caller-supplied label (e.g. _NET_CLOSE_WINDOW, _NET_ACTIVE_WINDOW). Failure usually means a bad X connection or bad event/parameters.

Source

Thrown at contrib/x11/src/jnacontrib/x11/api/X.java:1116

            event.serial = new NativeLong(0);
            event.send_event = 1;
            event.message_type = display.getAtom(msg);
            event.window = x11Window;
            event.format = 32;
            event.data.setType(NativeLong[].class);
            event.data.l[0] = data0;
            event.data.l[1] = data1;
            event.data.l[2] = data2;
            event.data.l[3] = data3;
            event.data.l[4] = data4;

            X11.XEvent e = new X11.XEvent();
            e.setTypedValue(event);

            if (x11.XSendEvent(display.x11Display, display.getRootWindow().x11Window, 0, mask, e) != 0) {
                return X11.Success;
            } else {
                throw new X11Exception("Cannot send " + msg + " event.");
            }
        }

        public Window[] getSubwindows() throws X11Exception {
            WindowByReference root = new WindowByReference();
            WindowByReference parent = new WindowByReference();
            PointerByReference children = new PointerByReference();
            IntByReference childCount = new IntByReference();

            if (x11.XQueryTree(display.x11Display, x11Window, root, parent, children, childCount) == 0){
                throw new X11Exception("Can't query subwindows");
            }

            if( childCount.getValue() == 0 ){
                return null;
            }

            Window[] retVal = new Window[ childCount.getValue() ];

View on GitHub (pinned to d036ad9781)

Solutions

  1. Re-acquire the target Window handle immediately before sending
  2. Verify the X connection is alive (try a cheap call like getDefaultRootWindow first)
  3. Check that the event struct/atom name matches what the WM expects (EWMH client messages need message_type + data.l[0..4])
  4. Catch X11Exception around sendEvent and treat failure as a user-visible 'operation failed'

Example fix

// before
win.sendEvent(x11.XInternAtom(display, "_NET_ACTIVE_WINDOW", false), ...);
// after
try {
    win.sendEvent(x11.XInternAtom(display, "_NET_ACTIVE_WINDOW", false), ...);
} catch (X11Exception e) {
    // window may have closed; re-resolve and retry once
    win = x.getWindowByName(title);
    if (win != null) win.sendEvent(...);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure target window still exists before sending
Window[] wins = x.getWindows(); // re-resolve; null/absent means skip send
boolean targetAlive = java.util.Arrays.stream(wins).anyMatch(w -> w == win);

Try / catch

try {
    win.sendEvent(atom, detail, mask);
} catch (X11Exception e) {
    Window fresh = x.getWindowByName(title);
    if (fresh != null) fresh.sendEvent(atom, detail, mask);
    else log.warn("target window gone, event not sent");
}

Prevention

When it happens

Trigger: Sending a client message such as _NET_ACTIVE_WINDOW or _NET_CLOSE_WINDOW via sendEvent when the X server rejects it: invalid target window id, malformed XEvent struct, or dead display connection.

Common situations: Sending an event to a window that was closed between lookup and send, running on a disconnected/terminating X session, or JNA XEvent layout mismatch producing an X server BadValue error.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/1d2dbafb61c4012e. Report an issue: GitHub.