apache/dubbo · error · ClassCastException

value for idx in is not object

Error message

value %s for idx %d in %s is not object

What it means

Thrown by AbstractJsonUtilImpl.checkObjectList(List) when iterating rawList and an element is not a Map. The method casts an unchecked List<?> into List<Map<String,?>>, validating each entry; the first non-Map entry aborts with a ClassCastException naming the value, its index, and the whole list.getListOfObjects delegates to getList then checkObjectList, so the same exception surfaces through that path.

Solutions

  1. Validate or filter the list before calling checkObjectList: rawList.stream().filter(Map.class::isInstance).map(m -> (Map<String,?>) m).collect(toList()).
  2. If the schema requires all-object entries, reject/fix the upstream payload that produced a scalar entry.
  3. Use getList (untyped) if you must tolerate heterogeneous entries, then handle each element by type.
  4. Catch ClassCastException and report the offending index for triage.

Example fix

// before
List<Map<String,?>> rows = jsonUtil.checkObjectList(raw); // contains a stray String
// after - filter to objects only
List<Map<String,?>> rows = raw.stream()
    .filter(Map.class::isInstance)
    .map(m -> (Map<String,?>) m)
    .collect(java.util.stream.Collectors.toList());
Defensive patterns

Strategy: type-guard

Validate before calling

List<?> raw = ...;
for (Object e : raw) {
    if (!(e instanceof Map)) {
        // filter or reject before calling checkObjectList
        raw = raw.stream().filter(Map.class::isInstance).collect(java.util.stream.Collectors.toList());
        break;
    }
}
return jsonUtil.checkObjectList(raw);

Type guard

private static boolean allObjects(List<?> rawList) {
    for (Object e : rawList) if (!(e instanceof Map)) return false;
    return true;
}

Try / catch

try {
    return jsonUtil.checkObjectList(rawList);
} catch (ClassCastException e) {
    // message names the offending index; fall back to filtering objects only
    return rawList.stream()
        .filter(Map.class::isInstance)
        .map(m -> (Map<String,?>) m)
        .collect(java.util.stream.Collectors.toList());
}

Prevention

When it happens

Trigger: jsonUtil.checkObjectList(rawList) (or getListOfObjects(obj,key)) where rawList contains at least one element that is not a Map — e.g. ["a", {"b":1}] or [1, 2, 3]. A list of pure objects passes.

Common situations: A JSON array of mixed types where a heterogeneous payload slips in; an array of scalars (strings/numbers) where an array of objects was expected; a flat list from an older API version; an error/status entry mixed into an otherwise-object array.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/a8363a741a6ca6e0. Report an issue: GitHub.

Appendix: source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/AbstractJsonUtilImpl.java:229

        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));
            }
        }
        return (List<Map<String, ?>>) rawList;
    }

    /**
     * Casts a list of unchecked JSON values to a list of String. If the given list
     * contains a value that is not a String, throws an exception.
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<String> checkStringList(List<?> rawList) {
        assert rawList != null;
        for (int i = 0; i < rawList.size(); i++) {
            if (!(rawList.get(i) instanceof String)) {
                throw new ClassCastException(
                        String.format("value '%s' for idx %d in '%s' is not string", rawList.get(i), i, rawList));

View on GitHub (pinned to 3a3043227f)