java-native-access/jna · error · Win32Exception

Win32Exception (error code from Native.getLastError after Fi

Error message

Win32Exception (error code from Native.getLastError after FindNextUrlCacheEntry)

What it means

WininetUtil.getCache() throws this Win32Exception when FindNextUrlCacheEntry fails with an error other than ERROR_NO_MORE_ITEMS, ERROR_SUCCESS, or ERROR_INSUFFICIENT_BUFFER while walking the cache. The exception carries the GetLastError() code so the developer can see the specific Win32 failure that interrupted enumeration. ERROR_NO_MORE_ITEMS is deliberately not thrown — it signals normal end of iteration.

Source

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

                throw new Win32Exception(Native.getLastError());
            }

            items.add(entry);

            while (true) {
                size = new IntByReference();

                // for every entry, we call the API twice:
                // once to get the size into the IntByReference
                // then again to get the actual item
                boolean result = Wininet.INSTANCE.FindNextUrlCacheEntry(cacheHandle, null, 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);
                    }
                }

                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) {

View on GitHub (pinned to d036ad9781)

Solutions

  1. Ensure enumeration happens on the same thread that opened the cache handle (WinINet thread affinity)
  2. Catch Win32Exception around getCache() and degrade gracefully (partial results or empty list)
  3. Check the specific error code to diagnose (e.g. ERROR_INVALID_HANDLE implies thread/session misuse)
  4. Keep enumeration short-lived or re-enumerate on failure instead of caching a long-lived FindFirstUrlCacheEntry handle

Example fix

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

Strategy: try-catch

Try / catch

try {
    items = WininetUtil.getCache();
} catch (Win32Exception e) {
    log.warn("cache enum failed: " + e.getMessage());
    items = partialOrEmpty();
}

Prevention

When it happens

Trigger: During the while-loop of getCache(), a call to Wininet.INSTANCE.FindNextUrlCacheEntry(cacheHandle, entry, size) returns false and GetLastError() is not one of the tolerated codes — e.g. an invalid handle because the cache handle was closed, or an internet-related hard error.

Common situations: Cache invalidated during a long enumeration; handle misuse across threads (WinINet handles must be used on the thread that created them); corrupted cache state.

Related errors


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