apache/dubbo · error · ClassCastException

value '%s' for key '%s' in '%s' is not object

Error message

value '%s' for key '%s' in '%s' is not object

What it means

Thrown by AbstractJsonUtilImpl.getObject(Map,String) when obj contains key but its value is not a java.util.Map. getObject returns null for an absent key; the exception fires only when the key is present but the value is a scalar, list, or other non-map type. It is a ClassCastException signalling that the JSON value is not a JSON object where one was expected.

Source

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

        }
        return checkStringList(list);
    }

    /**
     * Gets an object from an object for the given key.  If the key is not present, this returns null.
     * If the value is not a Map, throws an exception.
     */
    @SuppressWarnings("unchecked")
    @Override
    public Map<String, ?> getObject(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 Map)) {
            throw new ClassCastException(
                    String.format("value '%s' for key '%s' in '%s' is not object", value, key, obj));
        }
        return (Map<String, ?>) value;
    }

    /**
     * Gets a number from an object for the given key.  If the key is not present, this returns null.
     * If the value does not represent a double, throws an exception.
     */
    @Override
    public Double getNumberAsDouble(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 Double) {

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Inspect obj.get(key)'s runtime type and reconcile with the expected schema.
  2. If the field can be a string-id or a full object, branch on instanceof Map before calling getObject.
  3. Normalize the payload upstream so the field is always an object.
  4. Catch ClassCastException and surface the offending key for triage.

Example fix

// before
Map<String,?> user = jsonUtil.getObject(obj, "user");
// after - tolerate id-or-object
Object raw = obj.get("user");
Map<String,?> user = raw instanceof Map ? (Map<String,?>) raw : null;
Defensive patterns

Strategy: type-guard

Validate before calling

Object raw = obj.get(key);
if (raw != null && !(raw instanceof Map)) {
    // field present but not an object
    return null;
}
return jsonUtil.getObject(obj, key);

Type guard

private static boolean isObjectOrNull(Object value) {
    return value == null || value instanceof Map;
}

Try / catch

try {
    return jsonUtil.getObject(obj, key);
} catch (ClassCastException e) {
    log.warn("expected object at key={}, got value={}", key, obj.get(key));
    return null;
}

Prevention

When it happens

Trigger: jsonUtil.getObject(obj, key) where obj.get(key) exists and is a String/Number/Boolean/List (i.e. a JSON scalar or array) rather than a JSON object. Example JSON {"user": "alice"} with getObject(obj, "user").

Common situations: Field that was an object got flattened to a string/id by an API change; payload represents a one-of where the field is sometimes an object and sometimes a reference string; wrong key used against a schema where the field is an array; downstream returning an error string instead of an object.

Related errors


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