{"record":{"id":"af0f433bc74efe62","repo":"apache/pulsar","slug":"failed-to-parse-tlsfactoryconfig-as-a-json-object-af0f43","errorCode":null,"errorMessage":"Failed to parse tlsFactoryConfig as a JSON object","messagePattern":"Failed to parse tlsFactoryConfig as a JSON object","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/ClientTlsFactorySupport.java","lineNumber":367,"sourceCode":"     * <code>{</code> is parsed as a JSON object; otherwise it is parsed as a comma-separated\n     * {@code key=value} list.\n     *\n     * @param tlsFactoryConfig the configured factory params (may be null/blank)\n     * @return an immutable params map (possibly empty)\n     */\n    static Map<String, String> parseFactoryConfig(String tlsFactoryConfig) {\n        if (StringUtils.isBlank(tlsFactoryConfig)) {\n            return Map.of();\n        }\n        String trimmed = tlsFactoryConfig.trim();\n        if (trimmed.startsWith(\"{\")) {\n            try {\n                Map<String, String> parsed = ObjectMapperFactory.getMapper().reader()\n                        .forType(new TypeReference<Map<String, String>>() {})\n                        .readValue(trimmed);\n                return parsed == null ? Map.of() : Map.copyOf(parsed);\n            } catch (Exception e) {\n                throw new IllegalArgumentException(\"Failed to parse tlsFactoryConfig as a JSON object\", e);\n            }\n        }\n        Map<String, String> map = new LinkedHashMap<>();\n        for (String pair : trimmed.split(\",\")) {\n            String entry = pair.trim();\n            if (entry.isEmpty()) {\n                continue;\n            }\n            int eq = entry.indexOf('=');\n            if (eq < 0) {\n                map.put(entry, \"\");\n            } else {\n                map.put(entry.substring(0, eq).trim(), entry.substring(eq + 1).trim());\n            }\n        }\n        return Map.copyOf(map);\n    }\n","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/ClientTlsFactorySupport.java#L349-L385","documentation":"parseFactoryConfig parses the tlsFactoryConfig string, accepting either a JSON object mapping strings to strings or a comma-separated key=value list. If the string looks like JSON but cannot be parsed into Map<String,String>, an IllegalArgumentException is thrown. The config string is therefore malformed.","triggerScenarios":"Setting tlsFactoryConfig to invalid JSON such as \"{key: value}\" (unquoted keys), \"{...\" truncated JSON, or a value that is neither valid JSON nor a clean key=value list.","commonSituations":"Hand-editing the config with unquoted JSON keys; YAML/shell quoting stripping double quotes so only braces remain; mixing JSON and comma-list syntax; trailing commas.","solutions":["Provide valid JSON: {\"key1\":\"value1\",\"key2\":\"value2\"} with quoted keys and values.","Or use the simple comma form: key1=value1,key2=value2.","Validate the string with a JSON linter / JSON.parse before putting it in config.","Check shell/env quoting so double quotes are not stripped before the client sees the value."],"exampleFix":"// before\nString config = \"{keyA: valueA}\"; // invalid JSON\n// after\nString config = \"{\\\"keyA\\\":\\\"valueA\\\"}\"; // or \"keyA=valueA\"","handlingStrategy":"validation","validationCode":"String trimmed = tlsFactoryConfig.trim();\nif (trimmed.startsWith(\"{\")) {\n    try { new ObjectMapper().readValue(trimmed, new TypeReference<Map<String,String>>() {}); }\n    catch (Exception e) { throw new IllegalArgumentException(\"tlsFactoryConfig is not valid JSON\", e); }\n}","typeGuard":null,"tryCatchPattern":"try {\n    applyTlsFactoryConfig(raw);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Failed to parse tlsFactoryConfig\")) {\n        log.error(\"Use {\\\"k\\\":\\\"v\\\"} JSON or k=v,k2=v2 form\", e);\n    }\n}","preventionTips":["Prefer the simple k=v,k2=v2 form over JSON to avoid quoting pitfalls","Validate the config string with a JSON parser in tests","Mind shell/env quoting: double quotes may be stripped","Keep keys and values JSON-quoted if using JSON"],"tags":["tls","json","config","parsing"],"backgroundTag":"invalid-json-config","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}