grpc/grpc-java · error · IllegalArgumentException
The value of the map entry
Error message
The value of the map entry '${entry}' is of type '${value.getClass()}', which is not supported What it means
When building the channel from option maps (e.g. raw service-config or custom option maps), ManagedChannelImplBuilder normalizes each map entry value to String, Double, or Boolean. A value of any other type (e.g. nested Map, List, null wrapper) cannot be represented and triggers this IllegalArgumentException naming the offending key and its class.
Solutions
- Flatten nested values to supported types: String, Number, or Boolean before setting the option.
- Serialize nested structures to a JSON string if the option accepts textual config.
- Log/inspect the offending key ('entry') and fix its value type.
- Use typed builder methods (e.g. .maxInboundMessageSize(int)) instead of raw maps.
Example fix
// before
Map<String, Object> opts = new HashMap<>();
opts.put("serviceConfig", someNestedMap); // Map value
easyBuilder.build();
// after
opts.put("serviceConfig", jsonAsString); // String value Defensive patterns
Strategy: validation
Validate before calling
static void checkOptionTypes(Map<String, Object> opts) {
for (Map.Entry<String, Object> e : opts.entrySet()) {
Object v = e.getValue();
if (!(v instanceof String || v instanceof Number || v instanceof Boolean)) {
throw new IllegalArgumentException("option '" + e.getKey() + "' has unsupported type " + v.getClass());
}
}
} Type guard
boolean isSupportedOptionValue(Object v) {
return v instanceof String || v instanceof Number || v instanceof Boolean;
} Try / catch
try {
buildChannel(options);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("which is not supported")) {
log.error("Bad option map: {}", e.getMessage());
} else throw e;
} Prevention
- Restrict option maps to String/Number/Boolean values.
- Convert JSON parse trees to scalars before use.
- Use typed builder setters instead of raw maps.
When it happens
Trigger: Passing a Map<String,?> channel option or config map containing a nested Map, List, or custom object value for a key, then invoking the internal builder's map-parsing path.
Common situations: Constructing service config options programmatically with nested structures; JSON configs deserialized into java.util.LinkedHashMap values leaking into option maps; client interceptor option maps carrying POJOs.
Related errors
- The entry ' ' is of type ' ', which is not supported
- value ' ' for key ' ' in ' ' is not a number
- value ' ' for key ' ' in ' ' is not List
- value ' ' for key ' ' in ' ' is not object
- "allow_rules" is absent
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/21bbd356b54051d7.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java:632
entry.getKey() instanceof String,
"The key of the entry '%s' is not of String type", entry);
String key = (String) entry.getKey();
Object value = entry.getValue();
if (value == null) {
parsedMap.put(key, null);
} else if (value instanceof Map) {
parsedMap.put(key, checkMapEntryTypes((Map<?, ?>) value));
} else if (value instanceof List) {
parsedMap.put(key, checkListEntryTypes((List<?>) value));
} else if (value instanceof String) {
parsedMap.put(key, value);
} else if (value instanceof Number) {
parsedMap.put(key, ((Number) value).doubleValue());
} else if (value instanceof Boolean) {
parsedMap.put(key, value);
} else {
throw new IllegalArgumentException(
"The value of the map entry '" + entry + "' is of type '" + value.getClass()
+ "', which is not supported");
}
}
return Collections.unmodifiableMap(parsedMap);
}
private static List<?> checkListEntryTypes(List<?> list) {
List<Object> parsedList = new ArrayList<>(list.size());
for (Object value : list) {
if (value == null) {
parsedList.add(null);
} else if (value instanceof Map) {
parsedList.add(checkMapEntryTypes((Map<?, ?>) value));
} else if (value instanceof List) {
parsedList.add(checkListEntryTypes((List<?>) value));
} else if (value instanceof String) {
parsedList.add(value);View on GitHub (pinned to 64daddc1f3)