grpc/grpc-java · error · ResourceInvalidException
outlier_detection interval is not a valid Duration
Error message
outlier_detection interval is not a valid Duration
What it means
validateOutlierDetection checks the outlier_detection settings of a Cluster. If the interval duration proto is present but not a valid Duration (e.g. out-of-range seconds/nanos per Duration validation rules), the whole CDS resource is rejected with ResourceInvalidException.
Solutions
- Set a valid, normalized non-negative Duration for outlier_detection.interval on the management server
- Ensure seconds and nanos fields are within protobuf Duration bounds and correctly normalized
- Validate durations server-side before emitting CDS resources
Example fix
// before Durations.newBuilder().setSeconds(999999999999L).setNanos(0).build() // interval // after com.google.protobuf.Duration.newBuilder().setSeconds(10).setNanos(0).build() // interval = 10s
Defensive patterns
Strategy: validation
Validate before calling
io.envoyproxy.envoy.config.cluster.v3.OutlierDetection od = cluster.getOutlierDetection();
if (od.hasInterval() && !Durations.isValid(od.getInterval())) {
throw new IllegalArgumentException("interval is not a valid Duration");
}
if (od.hasInterval() && od.getInterval().getSeconds() < 0) {
throw new IllegalArgumentException("interval is negative");
} Try / catch
try {
cdsUpdate = xdsClusterResource.parseResource(args);
} catch (ResourceInvalidException e) {
if (e.getMessage().contains("not a valid Duration")) {
logger.atWarning().log("Rejecting cluster outlier_detection: %s", e.getMessage());
}
} Prevention
- Build Durations via Durations.fromMillis/fromSeconds to guarantee validity
- Never hand-set seconds/nanos without normalization
- Validate durations server-side before emitting outlier_detection settings
When it happens
Trigger: A Cluster's outlier_detection.interval is set with values outside Duration limits — negative seconds with wrong nanos normalization, or seconds/nanos exceeding protobuf Duration bounds — such that Durations.isValid returns false.
Common situations: Control-plane bugs producing unnormalized Duration protos; hand-built cluster protos in tests with seconds > 315,576,000,000 or malformed nanos; config converters translating durations incorrectly.
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
- Invalid duration in weighted round robin config: " +…
- outlier_detection base_ejection_time has a negative value
- outlier_detection base_ejection_time is not a valid Duration
- outlier_detection interval has a negative value
- outlier_detection max_ejection_time has a negative value
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/d3ee405a890bb669.
Report an issue: GitHub.
Appendix: source
Thrown at xds/src/main/java/io/grpc/xds/XdsClusterResource.java:378
"Cluster " + clusterName
+ ": LOGICAL DNS clusters socket_address must have port_value");
}
String dnsHostName = String.format(
Locale.US, "%s:%d", socketAddress.getAddress(), socketAddress.getPortValue());
return StructOrError.fromStruct(CdsUpdate.forLogicalDns(
clusterName, dnsHostName, lrsServerInfo, maxConcurrentRequests,
upstreamTlsContext, isHttp11ProxyAvailable, backendMetricPropagation));
}
return StructOrError.fromError(
"Cluster " + clusterName + ": unsupported built-in discovery type: " + type);
}
static io.envoyproxy.envoy.config.cluster.v3.OutlierDetection validateOutlierDetection(
io.envoyproxy.envoy.config.cluster.v3.OutlierDetection outlierDetection)
throws ResourceInvalidException {
if (outlierDetection.hasInterval()) {
if (!Durations.isValid(outlierDetection.getInterval())) {
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(View on GitHub (pinned to 64daddc1f3)