java-native-access/jna · error · RuntimeException

Expected GetTokenInformation to fail with ERROR_INSUFFICIENT

Error message

Expected GetTokenInformation to fail with ERROR_INSUFFICIENT_BUFFER

What it means

getTokenGroups sizes the TOKEN_GROUPS buffer by calling GetTokenInformation with a null buffer; per the Win32 contract this must fail with ERROR_INSUFFICIENT_BUFFER while writing the required size into tokenInformationLength. This RuntimeException signals the contract violation: the probe call unexpectedly succeeded. Like error [80], it points to an OS/JNA mapping mismatch rather than caller input.

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java:443

    public static Account getAccountBySid(String systemName, String sidString) {
        return getAccountBySid(systemName, new PSID(convertStringSidToSid(sidString)));
    }

    /**
     * This function returns the groups associated with a security token, such
     * as a user token.
     *
     * @param hToken
     *            Token.
     * @return Token groups.
     */
    public static Account[] getTokenGroups(HANDLE hToken) {
        // get token group information size
        IntByReference tokenInformationLength = new IntByReference();
        if (Advapi32.INSTANCE.GetTokenInformation(hToken,
                WinNT.TOKEN_INFORMATION_CLASS.TokenGroups, null, 0,
                tokenInformationLength)) {
            throw new RuntimeException(
                    "Expected GetTokenInformation to fail with ERROR_INSUFFICIENT_BUFFER");
        }
        int rc = Kernel32.INSTANCE.GetLastError();
        if (rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) {
            throw new Win32Exception(rc);
        }
        // get token group information
        WinNT.TOKEN_GROUPS groups = new WinNT.TOKEN_GROUPS(
                tokenInformationLength.getValue());
        if (!Advapi32.INSTANCE.GetTokenInformation(hToken,
                WinNT.TOKEN_INFORMATION_CLASS.TokenGroups, groups,
                tokenInformationLength.getValue(), tokenInformationLength)) {
            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
        }
        ArrayList<Account> userGroups = new ArrayList<>();
        // make array of names
        for (SID_AND_ATTRIBUTES sidAndAttribute : groups.getGroups()) {
            Account group;

View on GitHub (pinned to d036ad9781)

Solutions

  1. Upgrade to the latest com.sun.jna:jna and jna-platform so the GetTokenInformation mapping matches your OS
  2. Ensure tests/mocks model the real API: null buffer + ReturnLength must yield ERROR_INSUFFICIENT_BUFFER, not success
  3. Check that hToken is a real token handle from Advapi32.INSTANCE.OpenProcessToken/OpenThreadToken, not a fabricated HANDLE value
  4. As a workaround, preallocate a generous TOKEN_GROUPS buffer and call GetTokenInformation once, tolerating ERROR_INSUFFICIENT_BUFFER

Example fix

// before
Account[] groups = Advapi32Util.getTokenGroups(hToken);
// after - ensure the handle is genuine first
IntByReference tokType = new IntByReference();
if (!Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(),
        WinNT.TOKEN_QUERY, hToken)) {
    throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
Account[] groups = Advapi32Util.getTokenGroups(hToken);
Defensive patterns

Strategy: validation

Validate before calling

HANDLEByReference hRef = new HANDLEByReference();
if (!Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(),
        WinNT.TOKEN_QUERY, hRef)) {
    throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
if (!Platform.isWindows()) {
    throw new UnsupportedOperationException("token APIs require Windows");
}

Try / catch

try {
    Account[] groups = Advapi32Util.getTokenGroups(hToken);
} catch (RuntimeException e) {
    // probe-contract violation: log environment details, report to JNA
    throw new IllegalStateException("GetTokenInformation sizing call succeeded unexpectedly", e);
}

Prevention

When it happens

Trigger: Advapi32.INSTANCE.GetTokenInformation(hToken, TokenGroups, null, 0, tokenInformationLength) returns TRUE on the sizing call, triggering the RuntimeException at Advapi32Util.java:443; reached directly or via getCurrentUserGroups.

Common situations: Non-Windows or unusual Windows builds where the null-buffer probe succeeds; tests with a mocked Advapi32 that ignores the null-buffer convention; JNA version mismatches between jna and jna-platform.

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/358cbb91d2f574b5. Report an issue: GitHub.