java-native-access/jna · error · IllegalStateException

Mismatched allocated (X) vs. received devices count (Y)

Error message

Mismatched allocated (X) vs. received devices count (Y)

What it means

GetRawInputDeviceList was called with a pre-allocated RAWINPUTDEVICELIST array whose size was obtained via a first (count-query) call. If the actual number of devices returned differs from the array length, JNA throws this IllegalStateException because the buffer is inconsistent with the returned count, and returning partial/garbage records would be unsafe.

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/User32Util.java:109

    public static final List<RAWINPUTDEVICELIST> GetRawInputDeviceList() {
        IntByReference puiNumDevices = new IntByReference(0);
        RAWINPUTDEVICELIST placeholder = new RAWINPUTDEVICELIST();
        int cbSize = placeholder.sizeof();
        // first call is with NULL so we query the expected number of devices
        int returnValue = User32.INSTANCE.GetRawInputDeviceList(null, puiNumDevices, cbSize);
        if (returnValue != 0) {
            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
        }

        int deviceCount = puiNumDevices.getValue();
        RAWINPUTDEVICELIST[] records = (RAWINPUTDEVICELIST[]) placeholder.toArray(deviceCount);
        returnValue = User32.INSTANCE.GetRawInputDeviceList(records, puiNumDevices, cbSize);
        if (returnValue == (-1)) {
            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
        }

        if (returnValue != records.length) {
            throw new IllegalStateException("Mismatched allocated (" + records.length + ") vs. received devices count (" + returnValue + ")");
        }

        return Arrays.asList(records);
    }

    /**
     * Helper class, that runs a windows message loop as a seperate thread.
     *
     * This is intended to be used in conjunction with APIs, that need a
     * spinning message loop. One example for this are the DDE functions, that
     * can only be used if a message loop is present.
     *
     * To enable interaction with the mainloop the MessageLoopThread allows to
     * dispatch callables into the mainloop and let these Callables be invoked
     * on the message thread.
     *
     * This implies, that the Callables should block the loop as short as possible.
     */

View on GitHub (pinned to d036ad9781)

Solutions

  1. Catch the IllegalStateException and simply retry GetRawInputDeviceList — the second call re-queries the count and will usually succeed
  2. Call the method again inside a small retry loop (2-3 attempts) since the mismatch is inherently transient
  3. Avoid hot-plugging devices during enumeration in automated/test setups

Example fix

// before
List<RAWINPUTDEVICELIST> devices = User32Util.GetRawInputDeviceList();
// after
List<RAWINPUTDEVICELIST> devices;
try {
    devices = User32Util.GetRawInputDeviceList();
} catch (IllegalStateException e) {
    devices = User32Util.GetRawInputDeviceList(); // retry: device list changed mid-query
}
Defensive patterns

Strategy: retry

Validate before calling

// No pre-validation possible; just wrap the call in a bounded retry
List<RAWINPUTDEVICELIST> list;
for (int i = 0; i < 3; i++) {
    try { list = User32Util.GetRawInputDeviceList(); break; }
    catch (IllegalStateException e) { if (i == 2) throw e; }
}

Try / catch

try {
    devices = User32Util.GetRawInputDeviceList();
} catch (IllegalStateException e) {
    devices = User32Util.GetRawInputDeviceList(); // transient race
}

Prevention

When it happens

Trigger: Calling User32Util.GetRawInputDeviceList when raw input devices are plugged in or removed between the count-query call and the array-allocation call, so GetRawInputDeviceList returns a count different from the previously queried number.

Common situations: Hot-plugging/unplugging HID devices (mouse, keyboard, gamepad) between the two native calls; concurrent processes enumerating devices; virtualized/RDP environments where device lists change dynamically.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — 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/a69190704034c034. Report an issue: GitHub.