apache/pulsar · error · IllegalArgumentException

${key} already exists in the dynamicConfigurationMap

Error message

${key} already exists in the dynamicConfigurationMap

What it means

registerCustomDynamicConfiguration allows broker plugins to register custom dynamic configuration keys. It throws IllegalArgumentException if the key is already present in dynamicConfigurationMap, to prevent a plugin from silently overriding an existing (built-in or previously registered) configuration entry.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/BrokerService.java:3758

    }

    private void addDynamicConfigValidator(String key, Predicate<String> validator) {
        validateConfigKey(key);
        dynamicConfigurationMap.get(key).validator = validator;
    }

    private void validateConfigKey(String key) {
        if (!dynamicConfigurationMap.containsKey(key)) {
            throw new IllegalArgumentException(key + " doesn't exits in the dynamicConfigurationMap");
        }
    }

    /**
     * Allows the third-party plugin to register a custom dynamic configuration.
     */
    public void registerCustomDynamicConfiguration(String key, Predicate<String> validator) {
        if (dynamicConfigurationMap.containsKey(key)) {
            throw new IllegalArgumentException(key + " already exists in the dynamicConfigurationMap");
        }
        ConfigField configField = ConfigField.newCustomConfigField(null);
        configField.validator = validator;
        dynamicConfigurationMap.put(key, configField);
    }

    private void createDynamicConfigPathIfNotExist() {
        try {
            Optional<Map<String, String>> configCache =
                    pulsar().getPulsarResources().getDynamicConfigResources().getDynamicConfiguration();

            // create dynamic-config if not exist.
            if (!configCache.isPresent()) {
                pulsar().getPulsarResources().getDynamicConfigResources()
                        .setDynamicConfigurationWithCreate(n -> new HashMap<>());
            }
        } catch (Exception e) {
            log.warn().exception(e).log("Failed to read dynamic broker configuration");

View on GitHub (pinned to 820761864e)

Solutions

  1. Choose a unique, namespaced key for your custom configuration (e.g. prefix with your plugin name)
  2. Check dynamicConfigurationMap.containsKey(key) (or track your own registry) before registering
  3. Guard the registration with a first-run/one-time flag so reloads don't re-register
  4. Catch IllegalArgumentException and log/skip instead of failing broker startup

Example fix

// before
brokerService.registerCustomDynamicConfiguration("myConfig", validator);
// after
if (!brokerService.getDynamicConfigurationMap().containsKey("myplugin_myConfig")) {
    brokerService.registerCustomDynamicConfiguration("myplugin_myConfig", validator);
}
Defensive patterns

Strategy: validation

Validate before calling

if (!brokerService.getDynamicConfigurationMap().containsKey(key)) {
    brokerService.registerCustomDynamicConfiguration(key, validator);
}

Try / catch

try {
    brokerService.registerCustomDynamicConfiguration(key, validator);
} catch (IllegalArgumentException e) {
    log.warn("Custom config key {} already registered", key, e);
}

Prevention

When it happens

Trigger: Calling BrokerService.registerCustomDynamicConfiguration(key, validator) with a key that already exists — either a built-in Pulsar dynamic config key or one registered by another plugin or a prior registration call.

Common situations: Plugin hot-reload/re-initialization code that registers the same config key twice; a custom plugin using a config key name that collides with a Pulsar built-in dynamic configuration; two plugins registering the same key.

Related errors


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