{"record":{"id":"35f189258b173229","repo":"java-native-access/jna","slug":"win32exception-from-native-getlasterror-after-module32firstw","errorCode":null,"errorMessage":"Win32Exception from native GetLastError after Module32FirstW failed","messagePattern":"Win32Exception from native GetLastError after Module32FirstW failed","errorType":"error_code","errorClass":"Win32Exception","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java","lineNumber":1180,"sourceCode":"    /**\n     * Returns all the executable modules for a given process ID.<br>\n     *\n     * @param processID\n     *            The process ID to get executable modules for\n     * @return All the modules in the process.\n     */\n    public static List<Tlhelp32.MODULEENTRY32W> getModules(int processID) {\n        HANDLE snapshot = Kernel32.INSTANCE.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPMODULE, new DWORD(processID));\n        if (snapshot == null) {\n            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n        }\n\n        Win32Exception we = null;\n        try {\n            Tlhelp32.MODULEENTRY32W first = new Tlhelp32.MODULEENTRY32W();\n\n            if (!Kernel32.INSTANCE.Module32FirstW(snapshot, first)) {\n                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n            }\n\n            List<Tlhelp32.MODULEENTRY32W> modules = new ArrayList<>();\n            modules.add(first);\n\n            Tlhelp32.MODULEENTRY32W next = new Tlhelp32.MODULEENTRY32W();\n            while (Kernel32.INSTANCE.Module32NextW(snapshot, next)) {\n                modules.add(next);\n                next = new Tlhelp32.MODULEENTRY32W();\n            }\n\n            int lastError = Kernel32.INSTANCE.GetLastError();\n            // if we got a false from Module32Next,\n            // check to see if it returned false because we're genuinely done\n            // or if something went wrong.\n            if (lastError != W32Errors.ERROR_SUCCESS && lastError != W32Errors.ERROR_NO_MORE_FILES) {\n                throw new Win32Exception(lastError);\n            }","sourceCodeStart":1162,"sourceCodeEnd":1198,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java#L1162-L1198","documentation":"Kernel32Util.getModules throws this Win32Exception when Kernel32.INSTANCE.Module32FirstW returns false after a valid snapshot was created. The native GetLastError code explains why the first module entry could not be retrieved (e.g. ERROR_ACCESS_DENIED or a snapshot invalidated because the target process exited).","triggerScenarios":"Calling Kernel32Util.getModules(processID) where CreateToolhelp32Snapshot succeeded but Module32FirstW fails — typically because the target process terminated between snapshot creation and the first read, or the module list became inaccessible.","commonSituations":"Short-lived processes exiting between snapshot and Module32FirstW; processes still initializing with no modules listed yet; permission changes on the target process.","solutions":["Treat this as a race: catch Win32Exception and skip the process if it likely exited","Check errorCode and map ERROR_NO_MORE_FILES/ERROR_INVALID_PARAMETER to 'empty module list' rather than a hard failure","Retry getModules once after a short delay for volatile PIDs","Re-check the PID's existence (OpenProcess) before retrying"],"exampleFix":"// before\nList<Tlhelp32.MODULEENTRY32W> mods = Kernel32Util.getModules(pid);\n// after\nList<Tlhelp32.MODULEENTRY32W> mods;\ntry {\n    mods = Kernel32Util.getModules(pid);\n} catch (Win32Exception e) {\n    mods = Collections.emptyList(); // process exited before first module read\n}","handlingStrategy":"retry","validationCode":"HANDLE proc = Kernel32.INSTANCE.OpenProcess(WinNT.PROCESS_QUERY_LIMITED_INFORMATION, false, new DWORD(pid));\nif (proc == null) return Collections.emptyList(); // target exited before snapshot\nKernel32.INSTANCE.CloseHandle(proc);","typeGuard":"null","tryCatchPattern":"try {\n    mods = Kernel32Util.getModules(pid);\n} catch (Win32Exception e) {\n    // process likely exited between snapshot and Module32FirstW\n    mods = Collections.emptyList();\n}","preventionTips":["Expect races with short-lived processes and retry once","Treat empty/failed first reads as 'process vanished', not a system error","Avoid enumerating modules of processes you know are starting/stopping","Log errorCode to distinguish transient vs permission problems"],"tags":["win32","jni","native","processes"],"backgroundTag":"api-error-response","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}