What version of gRPC-Java are you using?
grpc-core_1.75.0
the issue also exists in grpc-core_1.81.0
What is your environment?
Microsoft Windows 11; openjdk version "21.0.10" 2026-01-20 LTS
What did you expect to see?
When using a service configuration, some fields of the configuration are expected to be Numeric.
Expectation is, that I can use Integer values here.
Given the following service configuration with a retry policy taken "as is" from the official documentation https://grpc.io/docs/guides/retry/#retry-configuration:
{
"methodConfig": [
{
"name": [{}],
"retryPolicy": {
"maxAttempts": 4,
"initialBackoff": "0.1s",
"maxBackoff": "1s",
"backoffMultiplier": 2,
"retryableStatusCodes": [
"UNAVAILABLE"
]
}
}
]
}
This should be an accepted retry policy.
"maxAttempt": 4 and "backoffMultiplier": 2 are valid (integer) values according to the documentation.
What did you see instead?
Using this retry policy example taken from the official grpc documentation fails to be parsed with the following Exception:
java.lang.IllegalArgumentException: The value of the map entry 'maxAttempts=4' is of type 'class java.lang.Integer', which is not supported.
grpc-java does only accepts Double-values.
The following service configuration is accepted though:
{
"methodConfig": [
{
"name": [{}],
"retryPolicy": {
"maxAttempts": 4.0,
"initialBackoff": "0.1s",
"maxBackoff": "1s",
"backoffMultiplier": 2.0,
"retryableStatusCodes": [
"UNAVAILABLE"
]
}
}
]
}
Please note that the integers 4 and 2 are replaced with Double values 4.0 and 2.0
Steps to reproduce the bug
Code used to create the ManagedChannel:
@Autowired private ObjectMapper objectMapper;
private static final String GRPC_SERVICE_CONFIGURATION =
"""
{
"methodConfig": [
{
"name": [{}],
"retryPolicy": {
"maxAttempts": 4,
"initialBackoff": "0.1s",
"maxBackoff": "1s",
"backoffMultiplier": 2,
"retryableStatusCodes": [
"UNAVAILABLE"
]
}
}
]
}""";
private Map<String, ?> getGrpcServiceConfiguration() throws IOException {
return objectMapper.readValue(GRPC_SERVICE_CONFIGURATION, new TypeReference<>() {});
}
public ManagedChannel buildManagedChannel(ChannelKey channelKey) throws IOException {
return ManagedChannelBuilder.forAddress(channelKey.host, channelKey.port)
.usePlaintext()
.defaultServiceConfig(getGrpcServiceConfiguration()) // <== throws unexpected IllegalArgumentException
.enableRetry()
.build();
}
Error Message & StackTrace:
java.lang.IllegalArgumentException: The value of the map entry 'maxAttempts=3' is of type 'class java.lang.Integer', which is not supported
at io.grpc.internal.ManagedChannelImplBuilder.checkMapEntryTypes(ManagedChannelImplBuilder.java:588)
at io.grpc.internal.ManagedChannelImplBuilder.checkMapEntryTypes(ManagedChannelImplBuilder.java:577)
at io.grpc.internal.ManagedChannelImplBuilder.checkListEntryTypes(ManagedChannelImplBuilder.java:601)
at io.grpc.internal.ManagedChannelImplBuilder.checkMapEntryTypes(ManagedChannelImplBuilder.java:579)
at io.grpc.internal.ManagedChannelImplBuilder.defaultServiceConfig(ManagedChannelImplBuilder.java:556)
at io.grpc.internal.ManagedChannelImplBuilder.defaultServiceConfig(ManagedChannelImplBuilder.java:72)
at io.grpc.ForwardingChannelBuilder2.defaultServiceConfig(ForwardingChannelBuilder2.java:250)
The Integer Type is rejected in ManagedChannelImplBuilder.checkMapEntryTypes:
https://github.com/grpc/grpc-java/blob/v1.75.x/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java#L582-L590:
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);
} else if (value instanceof Double) { // <==== only accepts numerics of type Double (should accept Number instead imo)
parsedList.add(value);
} else if (value instanceof Boolean) {
parsedList.add(value);
} else {
throw new IllegalArgumentException(
"The entry '" + value + "' is of type '" + value.getClass()
+ "', which is not supported");
}
}
return Collections.unmodifiableList(parsedList);
}
Imo, instead of checking for java.lang.Double, grpc-java should accept any instance of type java.lang.Number.
What version of gRPC-Java are you using?
grpc-core_1.75.0
the issue also exists in grpc-core_1.81.0
What is your environment?
Microsoft Windows 11; openjdk version "21.0.10" 2026-01-20 LTS
What did you expect to see?
When using a service configuration, some fields of the configuration are expected to be Numeric.
Expectation is, that I can use Integer values here.
Given the following service configuration with a retry policy taken "as is" from the official documentation https://grpc.io/docs/guides/retry/#retry-configuration:
This should be an accepted retry policy.
"maxAttempt": 4and"backoffMultiplier": 2are valid (integer) values according to the documentation.What did you see instead?
Using this retry policy example taken from the official grpc documentation fails to be parsed with the following Exception:
java.lang.IllegalArgumentException: The value of the map entry 'maxAttempts=4' is of type 'class java.lang.Integer', which is not supported.grpc-java does only accepts Double-values.
The following service configuration is accepted though:
Please note that the integers
4and2are replaced with Double values4.0and2.0Steps to reproduce the bug
Code used to create the ManagedChannel:
Error Message & StackTrace:
The Integer Type is rejected in ManagedChannelImplBuilder.checkMapEntryTypes:
https://github.com/grpc/grpc-java/blob/v1.75.x/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java#L582-L590:
Imo, instead of checking for java.lang.Double, grpc-java should accept any instance of type java.lang.Number.