java-native-access/jna · error · RuntimeException

LookupAccountNameW was expected to fail with ERROR_INSUFFICI

Error message

LookupAccountNameW was expected to fail with ERROR_INSUFFICIENT_BUFFER

What it means

Advapi32Util.getAccountByName first calls LookupAccountNameW with null buffers purely to query the required SID and domain-name buffer sizes; the Win32 contract says this probe call must fail with ERROR_INSUFFICIENT_BUFFER. This RuntimeException is thrown when the probe unexpectedly SUCCEEDS, meaning JNA's two-call size-probe protocol invariant was violated. It almost always indicates an OS/JNA mapping mismatch rather than bad user input.

Source

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

    }

    /**
     * Retrieves a security identifier (SID) for a given account.
     *
     * @param systemName
     *            Name of the system.
     * @param accountName
     *            Account name.
     * @return A structure containing the account SID.
     */
    public static Account getAccountByName(String systemName, String accountName) {
        IntByReference pSid = new IntByReference(0);
        IntByReference cchDomainName = new IntByReference(0);
        PointerByReference peUse = new PointerByReference();

        if (Advapi32.INSTANCE.LookupAccountName(systemName, accountName, null,
                pSid, null, cchDomainName, peUse)) {
            throw new RuntimeException(
                    "LookupAccountNameW was expected to fail with ERROR_INSUFFICIENT_BUFFER");
        }

        int rc = Kernel32.INSTANCE.GetLastError();
        if (pSid.getValue() == 0 || rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) {
            throw new Win32Exception(rc);
        }

        Memory sidMemory = new Memory(pSid.getValue());
        PSID result = new PSID(sidMemory);
        char[] referencedDomainName = new char[cchDomainName.getValue() + 1];

        if (!Advapi32.INSTANCE.LookupAccountName(systemName, accountName,
                result, pSid, referencedDomainName, cchDomainName, peUse)) {
            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
        }

        Account account = new Account();

View on GitHub (pinned to d036ad9781)

Solutions

  1. Verify you are running on a real Windows platform with a matching jna-platform version; upgrade com.sun.jna:jna-platform to the latest release
  2. Check the accountName string - trim whitespace and pass a plain account name (e.g. 'Administrators') rather than an empty or special string
  3. If it happens in tests, ensure the Advapi32 mock/stub follows the real contract: null-buffer call must fail with ERROR_INSUFFICIENT_BUFFER
  4. Report to JNA if a specific Windows build makes the sizing call return TRUE; meanwhile call LookupAccountName once with a large preallocated buffer instead of the two-call pattern

Example fix

// before (library internals - workaround on caller side)
Account a = Advapi32Util.getAccountByName(null, userName);
// after - guard the input first
if (userName == null || userName.trim().isEmpty()) {
    throw new IllegalArgumentException("accountName must be a non-empty Windows account name");
}
Account a = Advapi32Util.getAccountByName(null, userName);
Defensive patterns

Strategy: validation

Validate before calling

if (accountName == null || accountName.trim().isEmpty()) {
    throw new IllegalArgumentException("accountName must be a non-empty Windows account name");
}
if (!Platform.isWindows()) {
    throw new UnsupportedOperationException("getAccountByName requires Windows");
}

Try / catch

try {
    Account a = Advapi32Util.getAccountByName(systemName, accountName);
} catch (RuntimeException | Win32Exception e) {
    // invariant violation: report/log, do not retry blindly
    throw new IllegalStateException("SID size-probe contract violated", e);
}

Prevention

When it happens

Trigger: Advapi32.INSTANCE.LookupAccountName(systemName, accountName, null, pSid, null, cchDomainName, peUse) returns TRUE on the sizing call, so the expected failure path never runs and the RuntimeException at Advapi32Util.java:198 is thrown.

Common situations: Running on a Windows version or non-Windows stub where the underlying LookupAccountNameW behaves differently than the documented contract; passing an account name whose resolution needs no buffer; JNA native-mapping bugs or tests running against a mocked Advapi32 that returns success for null-buffer calls.

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/5e36966e3f8b111f. Report an issue: GitHub.