{"record":{"id":"11a132d07d7111a5","repo":"java-native-access/jna","slug":"jna-error-converting-error-message-d","errorCode":null,"errorMessage":"JNA: error converting error message: %d\n","messagePattern":"JNA: error converting error message: (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"native/dispatch.c","lineNumber":294,"sourceCode":"\ntypedef void (JNICALL* release_t)(JNIEnv*,jarray,void*,jint);\n\n#ifdef _WIN32\nstatic char*\nw32_format_error(int err) {\n  wchar_t* wbuf = NULL;\n  char* buf = NULL;\n  int wlen =\n    FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM\n                   |FORMAT_MESSAGE_IGNORE_INSERTS\n                   |FORMAT_MESSAGE_ALLOCATE_BUFFER,\n                   NULL, err, 0, (LPWSTR)&wbuf, 0, NULL);\n  if (wlen > 0) {\n    int bufSize = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, NULL, 0, NULL, NULL);\n    buf = (char*)malloc(bufSize);\n    int result = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, bufSize, NULL, NULL);\n    if (result == 0) {\n      fprintf(stderr, \"JNA: error converting error message: %d\\n\", (int)GET_LAST_ERROR());\n      free(buf);\n      buf = NULL;\n    }\n  }\n  if (wbuf) {\n    LocalFree(wbuf);\n  }\n\n  return buf;\n}\nstatic wchar_t*\nw32_short_name(JNIEnv* env, jstring str) {\n  wchar_t* wstr = newWideCString(env, str);\n  if (wstr && *wstr) {\n    DWORD required;\n    size_t size = wcslen(wstr) + 5;\n    wchar_t* prefixed = (wchar_t*)alloca(sizeof(wchar_t) * size);\n","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/native/dispatch.c#L276-L312","documentation":"On Windows, w32_format_error converts a system error code to text via FormatMessageW then WideCharToMultiByte(CP_UTF8). If the wide->UTF-8 conversion fails, JNA prints this message with GetLastError, frees the buffer, and continues with buf = NULL so the caller gets no error text. The original OS error code is still reported; only its human-readable message is lost.","triggerScenarios":"WideCharToMultiByte returns 0 while formatting a Win32 error message — e.g. malloc'd bufSize mismatch, invalid characters for CP_UTF8, or the GetLastError value being clobbered by intermediate calls (malloc/LocalFree) before reading it.","commonSituations":"Reporting obscure Win32 error codes (rare locale-specific messages), memory pressure making malloc fail, GetLastError already reset by an intervening API call so conversion reports a spurious error.","solutions":["Save the original error code immediately after the failing Win32 call and use it instead of GET_LAST_ERROR() after intermediate calls.","Log the numeric error code and look it up manually (net helpmsg / errlook.exe).","Check available memory; ensure malloc(bufSize) succeeded before conversion.","Retry the failing Windows API to re-capture a convertible error message."],"exampleFix":"// before\nint result = WideCharToMultiByte(...);\nif (result == 0) { fprintf(stderr, \"... %d\\n\", (int)GET_LAST_ERROR()); }\n// after\nDWORD originalErr = err; // captured right after the failing API\nif (result == 0) { fprintf(stderr, \"fmt failed (orig=%lu, conv=%d)\\n\", originalErr, (int)GET_LAST_ERROR()); }","handlingStrategy":"validation","validationCode":"// Capture and check the OS error code immediately after the failing Windows API\nDWORD err = GetLastError();\nif (err != 0) { /* record err now, before any malloc/LocalFree clobbers it */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Capture GetLastError() before any intervening API calls","Check malloc return before WideCharToMultiByte","Log numeric Win32 error codes and decode with errlook.exe","Test error-path formatting on all target locales"],"tags":["windows","win32","error-formatting","encoding"],"backgroundTag":"error-message-conversion-failed","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"}