grpc/grpc-java · error · IllegalArgumentException
Unknown denominator type of ${percent}
Error message
Unknown denominator type of ${percent} What it means
When converting a drop_overload percentage into a rate-per-million, getRatePerMillion switches on the FractionalPercent denominator. A UNRECOGNIZED or unset denominator hits the default branch and throws IllegalArgumentException, meaning the EDS resource carried a percent value the proto enum could not resolve.
Source
Thrown at xds/src/main/java/io/grpc/xds/XdsEndpointResource.java:182
io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment.Policy.DropOverload proto) {
return DropOverload.create(proto.getCategory(), getRatePerMillion(proto.getDropPercentage()));
}
private static int getRatePerMillion(FractionalPercent percent) {
int numerator = percent.getNumerator();
FractionalPercent.DenominatorType type = percent.getDenominator();
switch (type) {
case TEN_THOUSAND:
numerator *= 100;
break;
case HUNDRED:
numerator *= 10_000;
break;
case MILLION:
break;
case UNRECOGNIZED:
default:
throw new IllegalArgumentException("Unknown denominator type of " + percent);
}
if (numerator > 1_000_000 || numerator < 0) {
numerator = 1_000_000;
}
return numerator;
}
@VisibleForTesting
@Nullable
static StructOrError<LocalityLbEndpoints> parseLocalityLbEndpoints(
io.envoyproxy.envoy.config.endpoint.v3.LocalityLbEndpoints proto)
throws ResourceInvalidException {
// Filter out localities without or with 0 weight.
if (!proto.hasLoadBalancingWeight() || proto.getLoadBalancingWeight().getValue() < 1) {
return null;
}View on GitHub (pinned to 64daddc1f3)
Solutions
- Set denominator explicitly to HUNDRED, TEN_THOUSAND, or MILLION on drop_overload percent
- Rebuild/align control-plane protos with the grpc-java xDS proto versions
- Validate drop_overload percentages before sending EDS updates
- Note this surfaces as IllegalArgumentException (internal), typically causing the EDS watch to fail — fix at the config source
Example fix
# before
drop_overloads:
- category: "lb"
drop_percentage: { numerator: 5 } # denominator unset
# after
drop_overloads:
- category: "lb"
drop_percentage: { numerator: 5, denominator: HUNDRED } Defensive patterns
Strategy: validation
Validate before calling
for (DropOverload d : assignment.getPolicy().getDropOverloadsList()) {
if (d.getDropPercentage().getDenominator() == FractionalPercent.DenominatorType.UNRECOGNIZED
|| d.getDropPercentage().getDenominatorValue() == 0) {
throw new IllegalArgumentException("drop_percentage denominator unset/unknown");
}
} Try / catch
try {
update = XdsEndpointResource.getInstance().parse(args, resource);
} catch (IllegalArgumentException e) {
logger.warn("Bad drop_overload percent: {}", e.getMessage());
} Prevention
- Always set denominator (HUNDRED/TEN_THOUSAND/MILLION) on drop percentages
- Align proto versions between control plane and grpc-java so enum values resolve
- Reject UNRECOGNIZED denominators in control-plane validation
When it happens
Trigger: parseDropOverload passes a ClusterLoadAssignment drop_overload's FractionalPercent whose denominator is UNRECOGNIZED (unknown enum value from a newer/older proto, or zero-value misuse) into getRatePerMillion.
Common situations: Control plane built against a different protobuf version emitting an enum value grpc-java cannot resolve; hand-crafted drop_overload configs omitting denominator; proto wire corruption yielding UNRECOGNIZED.
Related errors
- Invalid message type: ${unpackedMessage.getClass()}
- ${structOrError.getErrorDetail()}
- ClusterLoadAssignment has duplicate locality:${locality} for
- ClusterLoadAssignment has sparse priorities
- Unknown denominator type: ${proto.getDenominator()}
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/7e53d2bdd6279d42.
Report an issue: GitHub.