apache/pulsar · error · IllegalArgumentException

The PIP-337 '${key}' client configuration key is removed in

Error message

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.

What it means

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.

Source

Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ConfigurationDataUtils.java:75

     *
     * @param config the client configuration map
     * @throws IllegalArgumentException if a removed PIP-337 key is present with a non-default value
     */
    public static void rejectRemovedPip337TlsFactoryKeys(Map<String, Object> config) {
        if (config == null) {
            return;
        }
        for (String key : REMOVED_PIP337_TLS_FACTORY_KEYS) {
            Object value = config.get(key);
            if (value == null || StringUtils.isBlank(value.toString())) {
                continue;
            }
            // A *Plugin key still set to the old default factory FQCN means no custom factory — tolerate it as
            // if unset. The *PluginParams keys carry no default value, so any non-blank value is rejected.
            if (key.endsWith("Plugin") && DEFAULT_PIP337_SSL_FACTORY_CLASS.equals(value.toString().trim())) {
                continue;
            }
            throw new IllegalArgumentException("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.");
        }
    }

    public static ObjectMapper create() {
        ObjectMapper mapper = ObjectMapperFactory.create();
        // forward compatibility for the properties may go away in the future
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
        mapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, false);
        mapper.setDefaultPropertyInclusion(Include.NON_NULL);
        return mapper;
    }

    private static final ObjectMapper MAPPER = create();

    private ConfigurationDataUtils() {}

View on GitHub (pinned to 820761864e)

Solutions

  1. Remove the removed PIP-337 '${key}' entry from the client configuration map/file.
  2. Configure the custom SSL factory via tlsFactoryClassName plus tlsFactoryConfig using a PulsarTlsFactory implementation instead of the old plugin mechanism.
  3. If the *Plugin key only holds the old default factory FQCN, delete it — it was tolerated as unset but should be cleaned up.
  4. Strip the removed keys defensively when loading legacy properties files (filter by key name before calling loadData).

Example fix

// before
Map<String, Object> conf = new HashMap<>();
conf.put("sslFactoryPlugin", "com.example.MySslFactory");
conf.put("sslFactoryPluginParams", "k=v");
ClientConfigurationData data = ConfigurationDataUtils.newConfigurationData(conf, ClientConfigurationData.class);
// after
Map<String, Object> conf = new HashMap<>();
conf.put("tlsFactoryClassName", "com.example.MyPulsarTlsFactory");
conf.put("tlsFactoryConfig", Map.of("k", "v"));
ClientConfigurationData data = ConfigurationDataUtils.newConfigurationData(conf, ClientConfigurationData.class);
Defensive patterns

Strategy: validation

Validate before calling

Set<String> removed = Set.of("sslFactoryPlugin", "sslFactoryPluginParams"); // extend with all PIP-337 keys
removed.forEach(k -> {
  if (configMap.containsKey(k)) throw new IllegalStateException("Removed PIP-337 key present: " + k);
});

Type guard

boolean hasRemovedPip337Keys(Map<String,Object> cfg) { return cfg.keySet().stream().anyMatch(k -> k.startsWith("sslFactory")); }

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Understand the failure class

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/4ae5599e3bec3780. Report an issue: GitHub.