apache/kafka · error · ClassCastException
Non-string value found in original settings for key entry.ge
Error message
Non-string value found in original settings for key entry.getKey(): (entry.getValue() == null ? null : entry.getValue().getClass().getName())
What it means
ClassCastException thrown by AbstractConfig.originalsStrings() when iterating the raw `originals` map and encountering a value that is not a String. originalsStrings() is documented to require all original settings to be strings; it constructs a Map<String,String> and casts each value. The message reports the offending key and (if non-null) the value's Java class name so the caller can see exactly which entry is mis-typed. This is a type-contract violation on the inputs supplied to the config constructor, not a parse error.
Source
Thrown at clients/src/main/java/org/apache/kafka/common/config/AbstractConfig.java:268
public Map<String, Object> originals(Map<String, Object> configOverrides) {
Map<String, Object> copy = new RecordingMap<>();
copy.putAll(originals);
copy.putAll(configOverrides);
return copy;
}
/**
* Get all the original settings, ensuring that all values are of type String.
*
* @return the original settings
* @throws ClassCastException if any of the values are not strings
*/
public Map<String, String> originalsStrings() {
Map<String, String> copy = new RecordingMap<>();
for (Map.Entry<String, ?> entry : originals.entrySet()) {
if (!(entry.getValue() instanceof String))
throw new ClassCastException("Non-string value found in original settings for key " + entry.getKey() +
": " + (entry.getValue() == null ? null : entry.getValue().getClass().getName()));
copy.put(entry.getKey(), (String) entry.getValue());
}
return copy;
}
/**
* Gets all original settings with the given prefix, stripping the prefix before adding it to the output.
*
* @param prefix the prefix to use as a filter
* @return a Map containing the settings with the prefix
*/
public Map<String, Object> originalsWithPrefix(String prefix) {
return originalsWithPrefix(prefix, true);
}
/**
* Gets all original settings with the given prefix.View on GitHub (pinned to c31c9215e1)
Solutions
- Supply originals as String values only (e.g. pass a Properties object or Map<String,String> with list values as comma-separated strings), so originalsStrings() can return them verbatim.
- If you need typed values, use the parsed accessors (getList, getInt, ...) instead of originalsStrings().
- Audit which key triggered the cast (named in the message) and convert that entry to a string at the source.
- Avoid mixing a pre-parsed Map<String,Object> with code that expects originalsStrings(); pick one representation.
Example fix
// before: originals contain a non-String value
Map<String, Object> originals = new HashMap<>();
originals.put("bootstrap.servers", Arrays.asList("host1:9092", "host2:9092"));
AbstractConfig config = new AbstractConfig(def, originals);
Map<String, String> strings = config.originalsStrings(); // ClassCastException: List
// after: pass originals as strings
Map<String, Object> originals = new HashMap<>();
originals.put("bootstrap.servers", "host1:9092,host2:9092");
AbstractConfig config = new AbstractConfig(def, originals);
Map<String, String> strings = config.originalsStrings(); // ok Defensive patterns
Strategy: type-guard
Validate before calling
// originalsStrings() requires every value to be a String; pre-filter or coerce.
java.util.Map<String, String> safe = new java.util.HashMap<>();
for (java.util.Map.Entry<String, ?> e : config.originals().entrySet()) {
Object v = e.getValue();
if (v instanceof String s) {
safe.put(e.getKey(), s);
} else if (v != null) {
safe.put(e.getKey(), String.valueOf(v)); // explicit coercion, no surprise CCE
}
} Type guard
boolean allOriginalsAreStrings(org.apache.kafka.common.config.AbstractConfig cfg) {
return cfg.originals().values().stream().allMatch(v -> v == null || v instanceof String);
} Try / catch
try {
Map<String, String> raw = config.originalsStrings();
} catch (ClassCastException cce) {
// message: "Non-string value found in original settings for key ..."
log.warn("Mixing typed and string originals is unsafe; coercing manually", cce);
Map<String, String> raw = config.originals().entrySet().stream()
.collect(java.util.stream.Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue() == null ? null : String.valueOf(e.getValue())));
} Prevention
- Build your Properties/Map with String values only when you plan to call originalsStrings().
- Do not mix parsed numeric/boolean values into the map you hand to the constructor if you later need originalsStrings().
- Prefer originals() (returns Map<String,?>) unless you specifically need String-only semantics.
When it happens
Trigger: Calling config.originalsStrings() after building an AbstractConfig from a Map<?,?> originals that contains a non-String value, e.g. a List (for a list-typed property supplied programmatically rather than as a comma-separated string), a Number/Boolean, or a Password object. Connect and some tools call originalsStrings() to externalize or log settings as strings.
Common situations: See trigger scenarios.
Related errors
- Unknown configuration '%s'
- Unexpected element of type klass.getClass().getName(), expec
- klass is not an instance of t.getName()
- lz4 doesn't support given compression level: level
- zstd doesn't support given compression level: level
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/02b0f33c2dee72d7.json.
Report an issue: GitHub.