{"record":{"id":"1dc66fbaa7f944a3","repo":"java-native-access/jna","slug":"unexpected-registry-type-lptype-getvalue-expected-reg-sz-or","errorCode":null,"errorMessage":"Unexpected registry type + lpType.getValue() + , expected REG_SZ or REG_EXPAND_SZ","messagePattern":"Unexpected registry type \\+ lpType\\.getValue\\(\\) \\+ , expected REG_SZ or REG_EXPAND_SZ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java","lineNumber":773,"sourceCode":"     *\n     * @param hKey\n     *            Parent Key.\n     * @param value\n     *            Name of the value to retrieve.\n     * @return String value.\n     */\n    public static String registryGetStringValue(HKEY hKey, String value) {\n        IntByReference lpcbData = new IntByReference();\n        IntByReference lpType = new IntByReference();\n        int rc = Advapi32.INSTANCE.RegQueryValueEx(hKey, value, 0,\n                lpType, (Pointer) null, lpcbData);\n        if (rc != W32Errors.ERROR_SUCCESS\n                && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) {\n            throw new Win32Exception(rc);\n        }\n        if (lpType.getValue() != WinNT.REG_SZ\n                && lpType.getValue() != WinNT.REG_EXPAND_SZ) {\n            throw new RuntimeException(\"Unexpected registry type \"\n                    + lpType.getValue()\n                    + \", expected REG_SZ or REG_EXPAND_SZ\");\n        }\n        if (lpcbData.getValue() == 0) {\n            return \"\";\n        }\n        // See comment in #registryGetValue\n        Memory mem = new Memory(lpcbData.getValue() + Native.WCHAR_SIZE);\n        mem.clear();\n        rc = Advapi32.INSTANCE.RegQueryValueEx(hKey, value, 0,\n                lpType, mem, lpcbData);\n        if (rc != W32Errors.ERROR_SUCCESS\n                && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) {\n            throw new Win32Exception(rc);\n        }\n        if (W32APITypeMapper.DEFAULT == W32APITypeMapper.UNICODE) {\n            return mem.getWideString(0);\n        } else {","sourceCodeStart":755,"sourceCodeEnd":791,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java#L755-L791","documentation":"A plain java.lang.RuntimeException thrown when the queried registry value's declared type is neither REG_SZ nor REG_EXPAND_SZ. registryGetStringValue only handles string values; a REG_DWORD, REG_BINARY, REG_MULTI_SZ, etc. value is rejected with this message (whose concatenation lists the numeric type code). Note the code builds the message via string concatenation, so the raw numeric type (e.g. 4 for REG_DWORD) appears in the text.","triggerScenarios":"Calling Advapi32Util.registryGetStringValue(root/hKey, ..., value) on a value stored as REG_DWORD (4), REG_BINARY (3), REG_MULTI_SZ (7), REG_QWORD (11) or any type other than 1 (REG_SZ) / 2 (REG_EXPAND_SZ); RegQueryValueEx succeeds but lpType.getValue() fails the type check.","commonSituations":"Registry value type changed by an installer or group policy between app versions; assuming all values under a key are strings; reading a DWORD 'flags' value with the string getter; migrating code from a generic registryGetValue call to the string-specific one.","solutions":["Use the type-appropriate getter: registryGetIntValue for REG_DWORD, registryGetBinaryValue for REG_BINARY, registryGetStringArray for REG_MULTI_SZ.","Inspect the type first via Advapi32Util.registryGetValue/registryQueryValue and dispatch on it.","Recreate the value as a REG_SZ if you own it (reg add /t REG_SZ or PowerShell Set-ItemProperty).","Catch RuntimeException from this call and fall back to a generic read + manual conversion.","Check whether the 32/64-bit view you query contains a differently typed value than expected (KEY_WOW64 flags)."],"exampleFix":"// before\nString v = Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, key, \"Timeout\"); // Timeout is REG_DWORD\n// after\nObject raw = Advapi32Util.registryGetValue(WinReg.HKEY_LOCAL_MACHINE, key, \"Timeout\");\nString v = (raw instanceof String) ? (String) raw : String.valueOf(raw);","handlingStrategy":"validation","validationCode":"// inspect the value type before choosing a getter\nObject raw = Advapi32Util.registryGetValue(root, key, value);\nif (raw != null && !(raw instanceof String)) {\n    throw new IllegalStateException(\"Value \" + value + \" is not REG_SZ (type=\" + raw.getClass().getSimpleName() + \")\");\n}","typeGuard":"static boolean isStringRegistryValue(HKEY root, String key, String value) {\n    Object v = Advapi32Util.registryGetValue(root, key, value);\n    return v instanceof String;\n}","tryCatchPattern":"try {\n    return Advapi32Util.registryGetStringValue(hKey, value);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Unexpected registry type\")) {\n        return String.valueOf(Advapi32Util.registryGetValue(hKey, value)); // fallback conversion\n    }\n    throw e;\n}","preventionTips":["Use registryGetValue to discover the type, then pick the typed getter.","Never assume all values under a key are strings - installers store DWORDs/binary freely.","For REG_MULTI_SZ use registryGetStringArray; REG_DWORD use registryGetIntValue.","Watch for type changes across application versions/group policy.","Use KEY_WOW64 flags to be sure you read the same view the value was written to."],"tags":["windows","registry","jna","type-mismatch"],"backgroundTag":"type-mismatch","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"}