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
- Upgrade to the latest com.sun.jna:jna and jna-platform so the GetTokenInformation mapping matches your OS
- Ensure tests/mocks model the real API: null buffer + ReturnLength must yield ERROR_INSUFFICIENT_BUFFER, not success
- Check that hToken is a real token handle from Advapi32.INSTANCE.OpenProcessToken/OpenThreadToken, not a fabricated HANDLE value
- 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
- Keep jna and jna-platform versions aligned and current
- Acquire the token via OpenProcessToken/OpenThreadToken with TOKEN_QUERY
- Prefer Advapi32Util.getCurrentUserGroups() over manual handle management
- Ensure test mocks replicate the ERROR_INSUFFICIENT_BUFFER sizing contract
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
- LookupAccountNameW was expected to fail with ERROR_INSUFFICI
- Failed to find privilege "{privilege}" - {GetLastError}
- Win32Exception from native GetLastError after ExpandEnvironm
- Win32Exception from native GetLastError after ExpandEnvironm
- Win32Exception from native GetLastError when GetPriorityClas
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/358cbb91d2f574b5.
Report an issue: GitHub.