grpc/grpc-java · error · ResourceInvalidException

outlier_detection base_ejection_time is not a valid Duration

Error message

outlier_detection base_ejection_time is not a valid Duration

What it means

validateOutlierDetection throws this ResourceInvalidException when the outlier_detection.base_ejection_time field is present but is not a valid protobuf Duration (Durations.isValid fails, e.g. nanos out of range). The gRPC xDS client rejects the whole Cluster resource because it cannot interpret the ejection duration. The config must be corrected at the management server before the cluster can load.

Source

Thrown at xds/src/main/java/io/grpc/xds/XdsClusterResource.java:386

    }
    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(
            "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()

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Correct base_ejection_time to a valid Duration, e.g. {seconds: 30}.
  2. Remove the field if you want the default base ejection time.
  3. Validate the CDS response with a protobuf Duration validator before pushing it.
  4. Fix the emitting control plane's duration serialization (normalize nanos into seconds).

Example fix

# before
outlier_detection:
  base_ejection_time: { nanos: 30000000000 }
# after
outlier_detection:
  base_ejection_time: { seconds: 30 }
Defensive patterns

Strategy: validation

Validate before calling

boolean validBaseEjectionTime(com.google.protobuf.Duration d) {
  return com.google.protobuf.util.Durations.isValid(d)
      && d.getNanos() >= 0 && d.getNanos() < 1000000000;
}

Type guard

boolean isValidProtoDuration(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("base_ejection_time")) {
    log.error("CDS resource rejected: fix base_ejection_time on the management server");
  }
}

Prevention

When it happens

Trigger: A Cluster resource from the xDS server carries outlier_detection.base_ejection_time with an invalid Duration value — nanos outside [0, 999999999] or seconds outside the representable range — detected in parseNonAggregateCluster via validateOutlierDetection.

Common situations: Malformed proto-JSON like {nanos: 1000000000} instead of {seconds: 1}; control-plane serialization bugs; hand-crafted test fixtures with placeholder durations; mixing -inf/NaN-like sentinels into duration fields.

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/9156e3c6d71ff566. Report an issue: GitHub.