apache/dubbo · error · ClassCastException
value '%s' for key '%s' in '%s' is not String
Error message
value '%s' for key '%s' in '%s' is not String
What it means
Thrown by AbstractJsonUtilImpl.getString(Map,String) when obj contains key but its value is not a String. getString returns null for an absent key, so this ClassCastException fires only when the key is present but the value is a Number, Boolean, Map, List, or other non-String reference. It signals a schema/type mismatch: a JSON scalar/object/array where a JSON string was expected.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/AbstractJsonUtilImpl.java:213
}
}
throw new IllegalArgumentException(String.format("value '%s' for key '%s' is not a long integer", value, key));
}
/**
* Gets a string from an object for the given key. If the key is not present, this returns null.
* If the value is not a String, throws an exception.
*/
@Override
public String getString(Map<String, ?> obj, String key) {
assert obj != null;
assert key != null;
if (!obj.containsKey(key)) {
return null;
}
Object value = obj.get(key);
if (!(value instanceof String)) {
throw new ClassCastException(
String.format("value '%s' for key '%s' in '%s' is not String", value, key, obj));
}
return (String) value;
}
/**
* Casts a list of unchecked JSON values to a list of checked objects in Java type.
* If the given list contains a value that is not a Map, throws an exception.
*/
@SuppressWarnings("unchecked")
@Override
public List<Map<String, ?>> checkObjectList(List<?> rawList) {
assert rawList != null;
for (int i = 0; i < rawList.size(); i++) {
if (!(rawList.get(i) instanceof Map)) {
throw new ClassCastException(
String.format("value %s for idx %d in %s is not object", rawList.get(i), i, rawList));
}View on GitHub (pinned to 3a3043227f)
Solutions
- Inspect obj.get(key)'s runtime type and reconcile with the expected schema.
- If the value may legitimately be non-string, coerce with String.valueOf(raw) before use.
- Normalize the producer to emit strings for that field.
- Catch ClassCastException and report the offending key/value for triage.
Example fix
// before
String name = jsonUtil.getString(obj, "name"); // name is Integer 42
// after - coerce safely
Object raw = obj.get("name");
String name = raw == null ? null : (raw instanceof String ? (String) raw : String.valueOf(raw)); Defensive patterns
Strategy: type-guard
Validate before calling
Object raw = obj.get(key);
if (raw != null && !(raw instanceof String)) {
return String.valueOf(raw); // coerce non-string scalars
}
return jsonUtil.getString(obj, key); Type guard
private static boolean isStringOrNull(Object value) {
return value == null || value instanceof String;
} Try / catch
try {
return jsonUtil.getString(obj, key);
} catch (ClassCastException e) {
Object raw = obj.get(key);
return raw == null ? null : String.valueOf(raw); // coerce instead of failing
} Prevention
- Coerce with String.valueOf when the field may be a non-string scalar.
- Validate the schema for fields read with getString.
- Reconcile with the producer when a string field changes to a number/boolean.
When it happens
Trigger: jsonUtil.getString(obj, key) where obj.get(key) exists and is not a String — e.g. JSON {"name": 42} or {"name": true} or {"name": {"first":"a"}} with getString(obj, "name").
Common situations: A field that was a string got changed to a number/boolean upstream; an ID field switching from numeric string to actual number; a conditional payload where the field is sometimes text and sometimes a structured object; an enum/code field returned as a number; localization turning a value into a nested object.
Related errors
- value '%s' for key '%s' in '%s' is not List
- value '%s' for key '%s' in '%s' is not object
- value %s for idx %d in %s is not object
- value '%s' for idx %d in '%s' is not string
- value '%s' for key '%s' in '%s' is not a number
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/a2d52bf3a32107a4.
Report an issue: GitHub.