grpc/grpc-java · error · ResourceInvalidException
outlier_detection max_ejection_time is not a valid Duration
Error message
outlier_detection max_ejection_time is not a valid Duration
What it means
validateOutlierDetection throws this ResourceInvalidException when outlier_detection.max_ejection_time is present but fails Durations.isValid, meaning it is not a well-formed protobuf Duration (nanos/seconds out of the allowed range). The xDS client cannot parse the value so it rejects the entire Cluster resource rather than guessing. This surfaces during parseNonAggregateCluster when processing a CDS response.
Source
Thrown at xds/src/main/java/io/grpc/xds/XdsClusterResource.java:396
throw new ResourceInvalidException("outlier_detection interval is not a valid Duration");
}
if (hasNegativeValues(outlierDetection.getInterval())) {
throw new ResourceInvalidException("outlier_detection interval has a negative value");
}
}
if (outlierDetection.hasBaseEjectionTime()) {
if (!Durations.isValid(outlierDetection.getBaseEjectionTime())) {
throw new ResourceInvalidException(
"outlier_detection base_ejection_time is not a valid Duration");
}
if (hasNegativeValues(outlierDetection.getBaseEjectionTime())) {
throw new ResourceInvalidException(
"outlier_detection base_ejection_time has a negative value");
}
}
if (outlierDetection.hasMaxEjectionTime()) {
if (!Durations.isValid(outlierDetection.getMaxEjectionTime())) {
throw new ResourceInvalidException(
"outlier_detection max_ejection_time is not a valid Duration");
}
if (hasNegativeValues(outlierDetection.getMaxEjectionTime())) {
throw new ResourceInvalidException(
"outlier_detection max_ejection_time has a negative value");
}
}
if (outlierDetection.hasMaxEjectionPercent()
&& outlierDetection.getMaxEjectionPercent().getValue() > 100) {
throw new ResourceInvalidException(
"outlier_detection max_ejection_percent is > 100");
}
if (outlierDetection.hasEnforcingSuccessRate()
&& outlierDetection.getEnforcingSuccessRate().getValue() > 100) {
throw new ResourceInvalidException(
"outlier_detection enforcing_success_rate is > 100");
}
if (outlierDetection.hasFailurePercentageThreshold()View on GitHub (pinned to 64daddc1f3)
Solutions
- Provide a valid Duration, e.g. max_ejection_time: {seconds: 300}.
- Remove the field to accept the default max ejection time.
- Normalize nanos into seconds at the config generator.
- Validate the resource with com.google.protobuf.util.Durations.isValid before emitting.
Example fix
# before
outlier_detection:
max_ejection_time: { nanos: 300000000000 }
# after
outlier_detection:
max_ejection_time: { seconds: 300 } Defensive patterns
Strategy: validation
Validate before calling
boolean validMaxEjectionTime(com.google.protobuf.Duration d) {
return com.google.protobuf.util.Durations.isValid(d)
&& d.getNanos() >= 0 && d.getNanos() < 1000000000;
} Type guard
boolean isNormalizedDuration(com.google.protobuf.Duration d) {
return d != null && com.google.protobuf.util.Durations.isValid(d);
} Try / catch
try {
parseCluster(resource);
} catch (io.grpc.xds.ResourceInvalidException e) {
if (e.getMessage().contains("max_ejection_time")) {
log.error("max_ejection_time malformed in CDS resource");
}
return null;
} Prevention
- Convert milliseconds to Durations via Durations.fromMillis, not manual nanos math.
- Assert Durations.isValid on every duration field before emitting proto JSON.
- Watch for ms-to-ns overflow when scaling time values.
- Test with realistic ejection times (30s base, 300s max).
When it happens
Trigger: A Cluster resource contains outlier_detection.max_ejection_time as an invalid Duration — for example nanos = 1e9 or more without carrying into seconds, or seconds beyond the Duration range — passing through validateOutlierDetection.
Common situations: Buggy control-plane serialization producing out-of-range nanos; hand-written JSON fixtures; tests using fake durations like {nanos: -999999999999}; tools converting milliseconds into nanos without normalization.
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
Related errors
- outlier_detection interval has a negative value
- outlier_detection base_ejection_time is not a valid Duration
- outlier_detection base_ejection_time has a negative value
- outlier_detection max_ejection_time has a negative value
- unsupported ExtAuthz service type: only grpc_service is supp
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/6a92f92c64aafb1f.
Report an issue: GitHub.