apache/dubbo · error · ClassCastException
value '%s' for key '%s' in '%s' is not List
Error message
value '%s' for key '%s' in '%s' is not List
What it means
Thrown by AbstractJsonUtilImpl.getList(Map,String) when obj contains key but its value is not a java.util.List. getList returns null for an absent key, so this exception only fires when the key IS present but the JSON value is a scalar, object, or other non-list type. It is a ClassCastException reflecting a schema/type mismatch between the JSON shape and the expected Java type. Subclasses (the JsonUtil impls) inherit this behavior.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/AbstractJsonUtilImpl.java:55
List<String> list = new LinkedList<>();
list.add("json");
return CollectionUtils.equals(list, toJavaList(toJson(list), String.class));
} catch (Throwable t) {
return false;
}
}
@Override
public List<?> getList(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 List)) {
throw new ClassCastException(String.format("value '%s' for key '%s' in '%s' is not List", value, key, obj));
}
return (List<?>) value;
}
/**
* Gets a list from an object for the given key, and verifies all entries are objects. If the key
* is not present, this returns null. If the value is not a List or an entry is not an object,
* throws an exception.
*/
@Override
public List<Map<String, ?>> getListOfObjects(Map<String, ?> obj, String key) {
assert obj != null;
List<?> list = getList(obj, key);
if (list == null) {
return null;
}
return checkObjectList(list);
}View on GitHub (pinned to 3a3043227f)
Solutions
- Confirm the actual runtime type of obj.get(key) and reconcile with the schema — typically the field shape changed upstream.
- If the field may legitimately be a scalar or a list, branch on instanceof List before calling getList.
- Switch to a more permissive accessor or normalize the JSON to the expected array shape upstream.
- Catch ClassCastException and report the offending key/value for triage.
Example fix
// before
List<?> items = jsonUtil.getList(obj, "items");
// after - tolerate single-or-list
Object raw = obj.get("items");
List<?> items = raw instanceof List ? (List<?>) raw : (raw == null ? null : List.of(raw)); Defensive patterns
Strategy: type-guard
Validate before calling
Object raw = obj.get(key);
if (raw != null && !(raw instanceof List)) {
// field present but not a list; decide policy before calling getList
return Collections.emptyList();
}
return jsonUtil.getList(obj, key); Type guard
private static boolean isListOfMapsOrEmpty(Object value) {
return value == null || value instanceof List;
} Try / catch
try {
return jsonUtil.getList(obj, key);
} catch (ClassCastException e) {
log.warn("expected list at key={}, got value={}", key, obj.get(key));
return null; // or a domain-specific fallback
} Prevention
- Branch on instanceof List before calling getList when the field may vary in shape.
- Pin and validate the JSON schema for fields you read with getList.
- Treat a single-object-where-list-expected as a schema change and reconcile with the producer.
When it happens
Trigger: jsonUtil.getList(obj, key) where obj.get(key) exists and is a Map, String, Number, Boolean, or null-reference that is not a List instance. For example JSON {"items": {"a":1}} with getList(obj, "items").
Common situations: API contract changed so a field that was an array became a single object (or vice versa); a conditional payload where the field is sometimes a list and sometimes a scalar; downstream service returning an error object instead of the expected array; using getList on a field the schema documents as an object.
Related errors
- value '%s' for key '%s' in '%s' is not object
- value '%s' for key '%s' in '%s' is not String
- 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/7d76bf6f40a16428.
Report an issue: GitHub.