grpc/grpc-java · error · ResourceInvalidException

outlier_detection max_ejection_percent is > 100

Error message

outlier_detection max_ejection_percent is > 100

What it means

This ResourceInvalidException is thrown when outlier_detection.max_ejection_percent exceeds 100. The field caps the percentage of hosts in a cluster that can be ejected for outlier status, so any value above 100 is invalid. validateOutlierDetection enforces this range while parsing the Cluster in parseNonAggregateCluster.

Solutions

  1. Set max_ejection_percent to a value in [0, 100] (Envoy default is 10).
  2. Multiply fraction-based values by 100 (0.5 -> 50) before emitting.
  3. Add range validation in the control plane before publishing the Cluster.
  4. If you truly need all hosts ejectable, set it to exactly 100, not more.

Example fix

# before
outlier_detection:
  max_ejection_percent: 150
# after
outlier_detection:
  max_ejection_percent: 100
Defensive patterns

Strategy: validation

Validate before calling

boolean validMaxEjectionPercent(io.envoyproxy.envoy.type.v3.UInt32Value v) {
  return v == null || v.getValue() <= 100;
}

Type guard

boolean inPercentRange(long v) {
  return v >= 0 && v <= 100;
}

Try / catch

try {
  cluster = parseCluster(raw);
} catch (io.grpc.xds.ResourceInvalidException e) {
  if (e.getMessage().contains("max_ejection_percent")) {
    log.error("max_ejection_percent > 100 in CDS resource; fix control plane");
  }
  return null;
}

Prevention

When it happens

Trigger: A Cluster resource contains outlier_detection.max_ejection_percent with a UInt32Value greater than 100 (e.g. 150). The check runs only when the field is present (hasMaxEjectionPercent()).

Common situations: Confusing the 0-100 percent scale with a 0-1 fraction and sending 1.0 as 1000; typos like 1000; control planes forwarding unvalidated user input from dashboards.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

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

    }
    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()
        && outlierDetection.getFailurePercentageThreshold().getValue() > 100) {
      throw new ResourceInvalidException(
          "outlier_detection failure_percentage_threshold is > 100");
    }
    if (outlierDetection.hasEnforcingFailurePercentage()
        && outlierDetection.getEnforcingFailurePercentage().getValue() > 100) {
      throw new ResourceInvalidException(
          "outlier_detection enforcing_failure_percentage is > 100");
    }

    return outlierDetection;
  }

  static boolean hasNegativeValues(Duration duration) {
    return duration.getSeconds() < 0 || duration.getNanos() < 0;

View on GitHub (pinned to 64daddc1f3)