java-native-access/jna · warning

JNA: error converting error message: %d

Error message

JNA: error converting error message: %d

What it means

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.

Source

Thrown at native/dispatch.c:294

typedef void (JNICALL* release_t)(JNIEnv*,jarray,void*,jint);

#ifdef _WIN32
static char*
w32_format_error(int err) {
  wchar_t* wbuf = NULL;
  char* buf = NULL;
  int wlen =
    FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
                   |FORMAT_MESSAGE_IGNORE_INSERTS
                   |FORMAT_MESSAGE_ALLOCATE_BUFFER,
                   NULL, err, 0, (LPWSTR)&wbuf, 0, NULL);
  if (wlen > 0) {
    int bufSize = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, NULL, 0, NULL, NULL);
    buf = (char*)malloc(bufSize);
    int result = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, bufSize, NULL, NULL);
    if (result == 0) {
      fprintf(stderr, "JNA: error converting error message: %d\n", (int)GET_LAST_ERROR());
      free(buf);
      buf = NULL;
    }
  }
  if (wbuf) {
    LocalFree(wbuf);
  }

  return buf;
}
static wchar_t*
w32_short_name(JNIEnv* env, jstring str) {
  wchar_t* wstr = newWideCString(env, str);
  if (wstr && *wstr) {
    DWORD required;
    size_t size = wcslen(wstr) + 5;
    wchar_t* prefixed = (wchar_t*)alloca(sizeof(wchar_t) * size);

View on GitHub (pinned to d036ad9781)

Solutions

  1. Save the original error code immediately after the failing Win32 call and use it instead of GET_LAST_ERROR() after intermediate calls.
  2. Log the numeric error code and look it up manually (net helpmsg / errlook.exe).
  3. Check available memory; ensure malloc(bufSize) succeeded before conversion.
  4. Retry the failing Windows API to re-capture a convertible error message.

Example fix

// before
int result = WideCharToMultiByte(...);
if (result == 0) { fprintf(stderr, "... %d\n", (int)GET_LAST_ERROR()); }
// after
DWORD originalErr = err; // captured right after the failing API
if (result == 0) { fprintf(stderr, "fmt failed (orig=%lu, conv=%d)\n", originalErr, (int)GET_LAST_ERROR()); }
Defensive patterns

Strategy: validation

Validate before calling

// Capture and check the OS error code immediately after the failing Windows API
DWORD err = GetLastError();
if (err != 0) { /* record err now, before any malloc/LocalFree clobbers it */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/11a132d07d7111a5. Report an issue: GitHub.