java-native-access/jna · error · Win32Exception

Win32Exception (error code from Native.getLastError after Fi

Error message

Win32Exception (error code from Native.getLastError after FindNextUrlCacheEntry with buffer)

What it means

Functionally the same failure as error 285 but thrown on the next loop iteration: after FindNextUrlCacheEntry reports ERROR_INSUFFICIENT_BUFFER (or ERROR_SUCCESS with a false return), the code allocates a new INTERNET_CACHE_ENTRY_INFO and the subsequent FindNextUrlCacheEntry call with the new buffer fails, producing a Win32Exception with the fresh GetLastError() code. It means a mid-enumeration retry with a resized buffer still failed.

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/WininetUtil.java:109

                if (!result) {
                    lastError = Native.getLastError();
                    if (lastError == WinError.ERROR_NO_MORE_ITEMS) {
                        break;
                    } else if (lastError != WinError.ERROR_SUCCESS && lastError != WinError.ERROR_INSUFFICIENT_BUFFER) {
                        throw new Win32Exception(lastError);
                    }
                }

                entry = new INTERNET_CACHE_ENTRY_INFO(size.getValue());
                result = Wininet.INSTANCE.FindNextUrlCacheEntry(cacheHandle, entry, size);

                if (!result) {
                    lastError = Native.getLastError();
                    if (lastError == WinError.ERROR_NO_MORE_ITEMS) {
                        break;
                    } else if (lastError != WinError.ERROR_SUCCESS && lastError != WinError.ERROR_INSUFFICIENT_BUFFER) {
                        throw new Win32Exception(lastError);
                    }
                }
                items.add(entry);
            }

            for (INTERNET_CACHE_ENTRY_INFO item : items) {
                cacheItems.put(item.lpszSourceUrlName.getWideString(0), item.lpszLocalFileName == null ? "" : item.lpszLocalFileName.getWideString(0));
            }

        } catch (Win32Exception e) {
            we = e;
        } finally {
            if (cacheHandle != null) {
                if (!Wininet.INSTANCE.FindCloseUrlCache(cacheHandle)) {
                    if (we != null) {
                        Win32Exception e = new Win32Exception(Native.getLastError());
                        e.addSuppressedReflected(we);
                        we = e;

View on GitHub (pinned to d036ad9781)

Solutions

  1. Retry the whole enumeration once on Win32Exception, since the cache is mutable and a fresh run usually succeeds
  2. Catch and treat as end-of-enumeration, returning items collected so far
  3. Run enumeration on the creating thread and avoid concurrent cache access
  4. Report/persist the error code for diagnosis rather than silently swallowing all Win32Exceptions

Example fix

// before
List<INTERNET_CACHE_ENTRY_INFO> items = WininetUtil.getCache();
// after
List<INTERNET_CACHE_ENTRY_INFO> items;
try {
    items = WininetUtil.getCache();
} catch (Win32Exception e) {
    items = Collections.emptyList(); // or retry once
}
Defensive patterns

Strategy: fallback

Try / catch

List<INTERNET_CACHE_ENTRY_INFO> items;
try {
    items = WininetUtil.getCache();
} catch (Win32Exception e) {
    items = Collections.emptyList(); // accept partial enumeration
}

Prevention

When it happens

Trigger: getCache() loop iteration where FindNextUrlCacheEntry returned false with ERROR_INSUFFICIENT_BUFFER, a bigger entry buffer was allocated, and the retry call still failed (entry removed concurrently, invalid handle, or hard WinINet error).

Common situations: Enumerating a very active cache where entries are being added/removed during iteration; thread-affinity violations of WinINet handles; allocation/structure-size mismatches on unusual Windows versions.

Related errors


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