java-native-access/jna · error · HeadlessException

KeyboardUtils requires a keyboard

Error message

KeyboardUtils requires a keyboard

What it means

KeyboardUtils' static initializer throws HeadlessException if the JVM reports a headless graphics environment, since the keyboard utilities need a real keyboard/display context. Class initialization fails and INSTANCE is never created.

Source

Thrown at contrib/platform/src/com/sun/jna/platform/KeyboardUtils.java:49

import com.sun.jna.platform.unix.X11;
import com.sun.jna.platform.unix.X11.Display;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinUser;

/** Provide access to the local keyboard state.  Note that this is meaningless
 * on a headless system and some VNC setups.
 *
 * @author twall
 */
// TODO: key clicks
// TODO: auto-repeat
// TODO: keyboard bell
// TODO: led state
public class KeyboardUtils {
    static final NativeKeyboardUtils INSTANCE;
    static {
        if (GraphicsEnvironment.isHeadless()) {
            throw new HeadlessException("KeyboardUtils requires a keyboard");
        }
        if (Platform.isWindows()) {
            INSTANCE = new W32KeyboardUtils();
        }
        else if (Platform.isMac()) {
            INSTANCE = new MacKeyboardUtils();
            throw new UnsupportedOperationException("No support (yet) for "
                                                    + System.getProperty("os.name"));
        }
        else {
            INSTANCE = new X11KeyboardUtils();
        }
    }

    public static boolean isPressed(int keycode, int location) {
        return INSTANCE.isPressed(keycode, location);
    }
    public static boolean isPressed(int keycode) {

View on GitHub (pinned to d036ad9781)

Solutions

  1. Run with a display available and java.awt.headless=false (use Xvfb on servers)
  2. Guard KeyboardUtils usage with !GraphicsEnvironment.isHeadless() checks
  3. Use a non-GUI input mechanism (e.g. JLine or native console reading) in headless environments

Example fix

// before
boolean pressed = KeyboardUtils.isPressed(KeyEvent.VK_SHIFT);
// after
if (GraphicsEnvironment.isHeadless()) {
    throw new IllegalStateException("KeyboardUtils requires a non-headless environment");
}
boolean pressed = KeyboardUtils.isPressed(KeyEvent.VK_SHIFT);
Defensive patterns

Strategy: validation

Validate before calling

if (GraphicsEnvironment.isHeadless()) {
    throw new IllegalStateException("KeyboardUtils requires a display (non-headless JVM)");
}

Type guard

boolean keyboardUtilsAvailable() {
    return !GraphicsEnvironment.isHeadless();
}

Try / catch

try {
    KeyboardUtils.isPressed(keycode);
} catch (HeadlessException | ExceptionInInitializerError e) {
    logger.warn("No keyboard available in this environment");
}

Prevention

When it happens

Trigger: Referencing KeyboardUtils (any static method like isPressed) while running with -Djava.awt.headless=true, or on a machine without display/input devices (servers, containers).

Common situations: CI pipelines and headless servers running key-listening code; Docker containers without X11; java.awt.headless explicitly set true in build/test configs.

Understand the failure class

Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.

Related errors


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