{"record":{"id":"4ae5599e3bec3780","repo":"apache/pulsar","slug":"the-pip-337-key-client-configuration-key-is-r","errorCode":null,"errorMessage":"The PIP-337 '${key}' client configuration key is removed in Pulsar 5.0 (PIP-478). Migrate the custom SSL factory to a PulsarTlsFactory selected by tlsFactoryClassName / tlsFactoryConfig and remove '${key}' from the configuration.","messagePattern":"The PIP-337 '(.+?)' client configuration key is removed in Pulsar 5\\.0 \\(PIP-478\\)\\. Migrate the custom SSL factory to a PulsarTlsFactory selected by tlsFactoryClassName / tlsFactoryConfig and remove '(.+?)' from the configuration\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ConfigurationDataUtils.java","lineNumber":75,"sourceCode":"     *\n     * @param config the client configuration map\n     * @throws IllegalArgumentException if a removed PIP-337 key is present with a non-default value\n     */\n    public static void rejectRemovedPip337TlsFactoryKeys(Map<String, Object> config) {\n        if (config == null) {\n            return;\n        }\n        for (String key : REMOVED_PIP337_TLS_FACTORY_KEYS) {\n            Object value = config.get(key);\n            if (value == null || StringUtils.isBlank(value.toString())) {\n                continue;\n            }\n            // A *Plugin key still set to the old default factory FQCN means no custom factory — tolerate it as\n            // if unset. The *PluginParams keys carry no default value, so any non-blank value is rejected.\n            if (key.endsWith(\"Plugin\") && DEFAULT_PIP337_SSL_FACTORY_CLASS.equals(value.toString().trim())) {\n                continue;\n            }\n            throw new IllegalArgumentException(\"The PIP-337 '\" + key + \"' client configuration key is \"\n                    + \"removed in Pulsar 5.0 (PIP-478). Migrate the custom SSL factory to a PulsarTlsFactory \"\n                    + \"selected by tlsFactoryClassName / tlsFactoryConfig and remove '\" + key + \"' from the \"\n                    + \"configuration.\");\n        }\n    }\n\n    public static ObjectMapper create() {\n        ObjectMapper mapper = ObjectMapperFactory.create();\n        // forward compatibility for the properties may go away in the future\n        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);\n        mapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, false);\n        mapper.setDefaultPropertyInclusion(Include.NON_NULL);\n        return mapper;\n    }\n\n    private static final ObjectMapper MAPPER = create();\n\n    private ConfigurationDataUtils() {}","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ConfigurationDataUtils.java#L57-L93","documentation":"PIP-478 (Pulsar 5.0) removed the PIP-337 per-connection SSL factory keys (e.g. sslFactoryPlugin / sslFactoryPluginParams style client config keys). During client configuration normalization, ConfigurationDataUtils rejects any of these removed keys unless the value is a *Plugin key still set to the old default factory FQCN (treated as unset). The exception aborts configuration loading with a message telling you to migrate to a PulsarTlsFactory.","triggerScenarios":"Passing a removed PIP-337 key in the client configuration map via ConfigurationDataUtils.loadData / ConfigurationDataUtils.newConfigurationData, e.g. building a ClientBuilder config from a properties file that still contains the old SSL factory plugin keys, or upgrading an existing client.properties / config map from Pulsar 3.x/4.x to 5.0.","commonSituations":"Upgrading a Pulsar client from 3.x to 5.0 while reusing old TLS config files; infrastructure-as-code templates or Helm charts that still inject the removed keys; sharing a single config map across brokers (which still accept them) and clients (which no longer do).","solutions":["Remove the removed PIP-337 '${key}' entry from the client configuration map/file.","Configure the custom SSL factory via tlsFactoryClassName plus tlsFactoryConfig using a PulsarTlsFactory implementation instead of the old plugin mechanism.","If the *Plugin key only holds the old default factory FQCN, delete it — it was tolerated as unset but should be cleaned up.","Strip the removed keys defensively when loading legacy properties files (filter by key name before calling loadData)."],"exampleFix":"// before\nMap<String, Object> conf = new HashMap<>();\nconf.put(\"sslFactoryPlugin\", \"com.example.MySslFactory\");\nconf.put(\"sslFactoryPluginParams\", \"k=v\");\nClientConfigurationData data = ConfigurationDataUtils.newConfigurationData(conf, ClientConfigurationData.class);\n// after\nMap<String, Object> conf = new HashMap<>();\nconf.put(\"tlsFactoryClassName\", \"com.example.MyPulsarTlsFactory\");\nconf.put(\"tlsFactoryConfig\", Map.of(\"k\", \"v\"));\nClientConfigurationData data = ConfigurationDataUtils.newConfigurationData(conf, ClientConfigurationData.class);","handlingStrategy":"validation","validationCode":"Set<String> removed = Set.of(\"sslFactoryPlugin\", \"sslFactoryPluginParams\"); // extend with all PIP-337 keys\nremoved.forEach(k -> {\n  if (configMap.containsKey(k)) throw new IllegalStateException(\"Removed PIP-337 key present: \" + k);\n});","typeGuard":"boolean hasRemovedPip337Keys(Map<String,Object> cfg) { return cfg.keySet().stream().anyMatch(k -> k.startsWith(\"sslFactory\")); }","tryCatchPattern":null,"preventionTips":["Audit client properties files and Helm charts for sslFactory* keys before upgrading to Pulsar 5.0.","Use tlsFactoryClassName/tlsFactoryConfig exclusively for custom SSL factories.","Add a startup-time config lint that fails fast on removed keys with a pointer to PIP-478."],"tags":["client-configuration","tls","upgrade","removed-api"],"backgroundTag":"removed-config-key","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}