grpc/grpc-java · 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
JsonUtil.getObject retrieves a key from a parsed JSON object and requires the value to be a JSON object (Map). If the key exists with any other type, it throws ClassCastException('value ... is not object'), embedding the offending value, key, and parent object in the message.
Source
Thrown at core/src/main/java/io/grpc/internal/JsonUtil.java:92
return null;
}
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")
@Nullable
public static Map<String, ?> getObject(Map<String, ?> obj, String key) {
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.
*/
@Nullable
public static Double getNumberAsDouble(Map<String, ?> obj, String key) {
assert key != null;
if (!obj.containsKey(key)) {
return null;
}
Object value = obj.get(key);
if (value instanceof Double) {
return (Double) value;View on GitHub (pinned to 64daddc1f3)
Solutions
- Fix the JSON so the key maps to an object: "key": {...} not "key": "..."
- Validate bootstrap/service-config JSON against the gRPC schema before startup
- Open the file named indirectly by the message and re-check the nesting of that key
- Regenerate the config with the tooling's current version to eliminate stale shapes
Example fix
// before
{"xds_server": "trafficdirector.googleapis.com"}
// after
{"xds_server": {"server_uri": "trafficdirector.googleapis.com", "channel_creds": [...]}} Defensive patterns
Strategy: validation
Validate before calling
Object v = cfg.get("node");
if (v != null && !(v instanceof Map)) throw new IllegalArgumentException("node must be a JSON object"); Type guard
@SuppressWarnings("unchecked")
Map<String,?> asObject(Object v) { return v instanceof Map ? (Map<String,?>) v : null; } Try / catch
try { JsonUtil.getObject(bootstrap, "node"); }
catch (ClassCastException e) { log.error("bad xDS bootstrap: {}", e.getMessage()); throw new InvalidConfigException(e); } Prevention
- Schema-validate xDS bootstrap and service-config files before startup
- Watch for field-shape changes when upgrading config generators
- Keep nesting correct: objects for sections, arrays for lists
When it happens
Trigger: Calling getObject/getList-of-objects on a JSON config where the key holds a scalar or array instead of a nested object — e.g. xDS bootstrap 'node' or 'xds_server' written as a string, or a nested section accidentally flattened.
Common situations: Hand-written gRPC service config / xDS bootstrap files with wrong nesting; version drift where a field changed from object to scalar between config generators; copy-paste errors merging JSON sections.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- value '%s' for key '%s' in '%s' is not List
- value '%s' for key '%s' in '%s' is not a number
- Authorization policy should be a JSON object. Found: null
- value '%s' for key '%s' is not a double
- Number expected to be integer:
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/9bee73af894a391e.
Report an issue: GitHub.