grpc/grpc-java · error · ResourceInvalidException

outlier_detection base_ejection_time has a negative value

Error message

outlier_detection base_ejection_time has a negative value

What it means

This ResourceInvalidException is raised when outlier_detection.base_ejection_time is a structurally valid Duration but contains negative seconds or nanos. validateOutlierDetection enforces that all outlier-detection durations are non-negative because a negative ejection time has no semantics. The Cluster resource is rejected and will not be applied.

Source

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

  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()
        && outlierDetection.getMaxEjectionPercent().getValue() > 100) {
      throw new ResourceInvalidException(
          "outlier_detection max_ejection_percent is > 100");
    }

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Set base_ejection_time to a positive duration (Envoy default is 30s, e.g. {seconds: 30}).
  2. Omit the field to use the library default.
  3. Add a pre-publish validation on the control plane rejecting negative durations.
  4. Audit any code computing durations by subtraction for clock-skew bugs.

Example fix

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

Strategy: validation

Validate before calling

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

Type guard

boolean nonNegative(com.google.protobuf.Duration d) {
  return d != null
      && com.google.protobuf.util.Durations.compare(d,
          com.google.protobuf.Duration.getDefaultInstance()) >= 0;
}

Try / catch

try {
  cluster = parseCluster(raw);
} catch (io.grpc.xds.ResourceInvalidException e) {
  log.warn("invalid outlier_detection config: {}", e.getMessage());
  return ClusterUpdate.unknownError();
}

Prevention

When it happens

Trigger: outlier_detection.base_ejection_time set to a negative duration, e.g. {seconds: -30} or {seconds: 0, nanos: -1}, in a Cluster resource parsed by parseNonAggregateCluster.

Common situations: Control-plane templates inserting -1 as 'not set'; manual YAML edits; generators that subtract timestamps to compute durations and go negative on clock skew.

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