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

  1. Provide a valid Duration, e.g. max_ejection_time: {seconds: 300}.
  2. Remove the field to accept the default max ejection time.
  3. Normalize nanos into seconds at the config generator.
  4. 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

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


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/6a92f92c64aafb1f. Report an issue: GitHub.