{"record":{"id":"5e36966e3f8b111f","repo":"java-native-access/jna","slug":"lookupaccountnamew-was-expected-to-fail-with-error","errorCode":null,"errorMessage":"LookupAccountNameW was expected to fail with ERROR_INSUFFICIENT_BUFFER","messagePattern":"LookupAccountNameW was expected to fail with ERROR_INSUFFICIENT_BUFFER","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java","lineNumber":198,"sourceCode":"    }\n\n    /**\n     * Retrieves a security identifier (SID) for a given account.\n     *\n     * @param systemName\n     *            Name of the system.\n     * @param accountName\n     *            Account name.\n     * @return A structure containing the account SID.\n     */\n    public static Account getAccountByName(String systemName, String accountName) {\n        IntByReference pSid = new IntByReference(0);\n        IntByReference cchDomainName = new IntByReference(0);\n        PointerByReference peUse = new PointerByReference();\n\n        if (Advapi32.INSTANCE.LookupAccountName(systemName, accountName, null,\n                pSid, null, cchDomainName, peUse)) {\n            throw new RuntimeException(\n                    \"LookupAccountNameW was expected to fail with ERROR_INSUFFICIENT_BUFFER\");\n        }\n\n        int rc = Kernel32.INSTANCE.GetLastError();\n        if (pSid.getValue() == 0 || rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) {\n            throw new Win32Exception(rc);\n        }\n\n        Memory sidMemory = new Memory(pSid.getValue());\n        PSID result = new PSID(sidMemory);\n        char[] referencedDomainName = new char[cchDomainName.getValue() + 1];\n\n        if (!Advapi32.INSTANCE.LookupAccountName(systemName, accountName,\n                result, pSid, referencedDomainName, cchDomainName, peUse)) {\n            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n        }\n\n        Account account = new Account();","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java#L180-L216","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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","Check the accountName string - trim whitespace and pass a plain account name (e.g. 'Administrators') rather than an empty or special string","If it happens in tests, ensure the Advapi32 mock/stub follows the real contract: null-buffer call must fail with ERROR_INSUFFICIENT_BUFFER","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"],"exampleFix":"// before (library internals - workaround on caller side)\nAccount a = Advapi32Util.getAccountByName(null, userName);\n// after - guard the input first\nif (userName == null || userName.trim().isEmpty()) {\n    throw new IllegalArgumentException(\"accountName must be a non-empty Windows account name\");\n}\nAccount a = Advapi32Util.getAccountByName(null, userName);","handlingStrategy":"validation","validationCode":"if (accountName == null || accountName.trim().isEmpty()) {\n    throw new IllegalArgumentException(\"accountName must be a non-empty Windows account name\");\n}\nif (!Platform.isWindows()) {\n    throw new UnsupportedOperationException(\"getAccountByName requires Windows\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    Account a = Advapi32Util.getAccountByName(systemName, accountName);\n} catch (RuntimeException | Win32Exception e) {\n    // invariant violation: report/log, do not retry blindly\n    throw new IllegalStateException(\"SID size-probe contract violated\", e);\n}","preventionTips":["Run only on supported Windows versions with a current jna-platform build","Keep jna and jna-platform artifacts at the same version","Never mock Advapi32 in tests without honoring the ERROR_INSUFFICIENT_BUFFER sizing contract","Validate accountName format before invoking the API"],"tags":["windows","win32","jna","sid-lookup","internal-invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}