java-native-access/jna · error · PdhException

PdhException(result)

Error message

PdhException(result)

What it means

PdhUtil.PdhLookupPerfNameByIndex translates a performance-counter index to its localized name via the PDH API. It wraps native return codes into PdhException; at this point the first (size-query) call returned a code that is neither ERROR_SUCCESS, PDH_MORE_DATA, nor PDH_INVALID_ARGUMENT, so the failure is raised immediately with the raw code.

Solutions

  1. Check the numeric code carried by PdhException against the PDH error constants to identify the exact failure
  2. Verify the counter index is valid for the target locale (compare against the counter table for that language)
  3. Repair performance-counter registry data (lodctr /r) if the table is corrupt
  4. If a remote machine name is passed, confirm the machine is reachable and remote performance monitoring is enabled

Example fix

// before
String name = PdhUtil.PdhLookupPerfNameByIndex(null, index);
// after
try {
    String name = PdhUtil.PdhLookupPerfNameByIndex(null, index);
} catch (PdhException e) {
    LOG.warn("No localized perf name for index " + index + ": " + e.getErrorCode());
    name = String.valueOf(index); // fallback
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (index <= 0) throw new IllegalArgumentException("performance counter index must be positive");

Try / catch

try { return PdhUtil.PdhLookupPerfNameByIndex(null, index); } catch (PdhException e) { LOG.warn("PDH lookup failed, code " + e.getErrorCode()); return null; }

Prevention

When it happens

Trigger: Calling PdhLookupPerfNameByIndex with an index that has no mapping in the current locale's counter table, or on a system where the PDH/performance counter registry data is damaged, returning codes like PDH_INVALID_HANDLE or PDH_CSTATUS_NO_MACHINE.

Common situations: Localizing counters across Windows versions/languages where index tables differ; missing or corrupt Perfc009.dat/PerfString.ini counter data; querying a machine (szMachineName) that is unreachable or has remote registry disabled.

Related errors


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

Appendix: source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/PdhUtil.java:71

     *            Null-terminated string that specifies the name of the computer
     *            where the specified performance object or counter is located.
     *            The computer name can be specified by the DNS name or the IP
     *            address. If NULL, the function uses the local computer.
     * @param dwNameIndex
     *            Index of the performance object or counter.
     * @return Returns the name of the performance object or counter.
     */
    public static String PdhLookupPerfNameByIndex(String szMachineName, int dwNameIndex) {
        // Call once with null buffer to get required buffer size
        DWORDByReference pcchNameBufferSize = new DWORDByReference(new DWORD(0));
        int result = Pdh.INSTANCE.PdhLookupPerfNameByIndex(szMachineName, dwNameIndex, null, pcchNameBufferSize);
        Memory mem = null;
        // Windows XP requires a non-null buffer and nonzero buffer size and
        // will return PDH_INVALID_ARGUMENT.
        if (result != PdhMsg.PDH_INVALID_ARGUMENT) {
            // Vista+ branch: use returned buffer size for second query
            if (result != WinError.ERROR_SUCCESS && result != Pdh.PDH_MORE_DATA) {
                throw new PdhException(result);
            }
            // Can't allocate 0 memory
            if (pcchNameBufferSize.getValue().intValue() < 1) {
                return "";
            }
            // Allocate buffer and call again
            mem = new Memory(pcchNameBufferSize.getValue().intValue() * CHAR_TO_BYTES);
            result = Pdh.INSTANCE.PdhLookupPerfNameByIndex(szMachineName, dwNameIndex, mem, pcchNameBufferSize);
        } else {
            // XP branch: try increasing buffer sizes until successful
            for (int bufferSize = 32; bufferSize <= Pdh.PDH_MAX_COUNTER_NAME; bufferSize *= 2) {
                pcchNameBufferSize = new DWORDByReference(new DWORD(bufferSize));
                mem = new Memory(bufferSize * CHAR_TO_BYTES);
                result = Pdh.INSTANCE.PdhLookupPerfNameByIndex(szMachineName, dwNameIndex, mem, pcchNameBufferSize);
                if (result != PdhMsg.PDH_INVALID_ARGUMENT && result != PdhMsg.PDH_INSUFFICIENT_BUFFER) {
                    break;
                }
            }

View on GitHub (pinned to d036ad9781)