apache/pulsar · error · RuntimeException

Failed to load config into existing configuration data

Error message

Failed to load config into existing configuration data

What it means

loadData merges an incoming config map into an existing configuration object's map, serializes the merged map to JSON, and deserializes it back into the target configuration class. Any Jackson IOException during that write/read cycle (unknown properties that aren't ignored, type mismatches between the map values and target field types, invalid JSON-convertible values) is rethrown as this RuntimeException.

Source

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

    private static final ObjectMapper MAPPER = create();

    private ConfigurationDataUtils() {}

    @SuppressWarnings("unchecked")
    public static <T> T loadData(Map<String, Object> config,
                                 T existingData,
                                 Class<T> dataCls) {
        try {
            String existingConfigJson = MAPPER.writeValueAsString(existingData);
            Map<String, Object> existingConfig = MAPPER.readValue(existingConfigJson, Map.class);
            Map<String, Object> newConfig = new HashMap<>();
            newConfig.putAll(existingConfig);
            newConfig.putAll(config);
            String configJson = MAPPER.writeValueAsString(newConfig);
            return MAPPER.readValue(configJson, dataCls);
        } catch (IOException e) {
            throw new RuntimeException("Failed to load config into existing configuration data", e);
        }

    }

}

View on GitHub (pinned to 820761864e)

Solutions

  1. Inspect the wrapped IOException cause for the exact field and value type mismatch.
  2. Convert values in the map to the correct Java types before calling loadData (e.g. parse numbers, booleans).
  3. Verify every key matches a field name on the target ConfigurationData class (typos produce coercion failures).
  4. Wrap the loadData call in try-catch and fall back to sanitized/validated config in the caller.

Example fix

// before
props.forEach((k, v) -> configMap.put(k, v)); // all Strings
// after
configMap.put("negativeAckRedeliveryDelayMs", Long.parseLong(props.getProperty("negativeAckRedeliveryDelayMs")));
Defensive patterns

Strategy: validation

Validate before calling

// Validate types before calling loadData
Objects.requireNonNull(configMap, "configMap");
configMap.forEach((k, v) -> System.out.println(k + " -> " + (v == null ? "null" : v.getClass().getSimpleName())));

Type guard

boolean isLoadable(Map<String,Object> cfg) { return cfg != null && cfg.values().stream().noneMatch(v -> v == null); }

Try / catch

try { return ConfigurationDataUtils.loadData(map, existing, ClientConfigurationData.class); } catch (RuntimeException e) { log.error("Config load failed", e.getCause()); throw new IllegalArgumentException("Invalid client configuration", e); }

Prevention

When it happens

Trigger: Calling ConfigurationDataUtils.loadData(configMap, existingConfig, SomeConfigurationData.class) where a map key maps to a field of an incompatible type (e.g. a String where an int or Map is expected), or a value that Jackson cannot serialize/deserialize.

Common situations: Loading client/producer/consumer config from properties files where all values are Strings but the target fields are typed (int, boolean, enums); passing a config map containing keys with wrong value types; typos in keys whose values then coerce incorrectly.

Related errors


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