grpc/grpc-go · error
OutlierDetectionLoadBalancingConfig.interval = %s; must be >
Error message
OutlierDetectionLoadBalancingConfig.interval = %s; must be >= 0
What it means
Returned by the outlier detection balancer's ParseConfig (internal/xds/balancer/outlierdetection/balancer.go:130) when the LBConfig `interval` field — a google.protobuf.Duration decoded into time.Duration — is negative. gRFC A50 mandates that interval, base_ejection_time, and max_ejection_time be non-negative, and the library enforces this in ParseConfig as defense-in-depth alongside the same check performed earlier in the xDS client. The default is 10s when the field is omitted.
Source
Thrown at internal/xds/balancer/outlierdetection/balancer.go:131
}
// Note: in the xds flow, these validations will never fail. The xdsclient
// performs the same validations as here on the xds Outlier Detection
// resource before parsing resource into JSON which this function gets
// called with. A50 defines two separate places for these validations to
// take place, the xdsclient and this ParseConfig method. "When parsing a
// config from JSON, if any of these requirements is violated, that should
// be treated as a parsing error." - A50
switch {
// "The google.protobuf.Duration fields interval, base_ejection_time, and
// max_ejection_time must obey the restrictions in the
// google.protobuf.Duration documentation and they must have non-negative
// values." - A50
// Approximately 290 years is the maximum time that time.Duration (int64)
// can represent. The restrictions on the protobuf.Duration field are to be
// within +-10000 years. Thus, just check for negative values.
case lbCfg.Interval < 0:
return nil, fmt.Errorf("OutlierDetectionLoadBalancingConfig.interval = %s; must be >= 0", lbCfg.Interval)
case lbCfg.BaseEjectionTime < 0:
return nil, fmt.Errorf("OutlierDetectionLoadBalancingConfig.base_ejection_time = %s; must be >= 0", lbCfg.BaseEjectionTime)
case lbCfg.MaxEjectionTime < 0:
return nil, fmt.Errorf("OutlierDetectionLoadBalancingConfig.max_ejection_time = %s; must be >= 0", lbCfg.MaxEjectionTime)
// "The fields max_ejection_percent,
// success_rate_ejection.enforcement_percentage,
// failure_percentage_ejection.threshold, and
// failure_percentage.enforcement_percentage must have values less than or
// equal to 100." - A50
case lbCfg.MaxEjectionPercent > 100:
return nil, fmt.Errorf("OutlierDetectionLoadBalancingConfig.max_ejection_percent = %v; must be <= 100", lbCfg.MaxEjectionPercent)
case lbCfg.SuccessRateEjection != nil && lbCfg.SuccessRateEjection.EnforcementPercentage > 100:
return nil, fmt.Errorf("OutlierDetectionLoadBalancingConfig.SuccessRateEjection.enforcement_percentage = %v; must be <= 100", lbCfg.SuccessRateEjection.EnforcementPercentage)
case lbCfg.FailurePercentageEjection != nil && lbCfg.FailurePercentageEjection.Threshold > 100:
return nil, fmt.Errorf("OutlierDetectionLoadBalancingConfig.FailurePercentageEjection.threshold = %v; must be <= 100", lbCfg.FailurePercentageEjection.Threshold)
case lbCfg.FailurePercentageEjection != nil && lbCfg.FailurePercentageEjection.EnforcementPercentage > 100:
return nil, fmt.Errorf("OutlierDetectionLoadBalancingConfig.FailurePercentageEjection.enforcement_percentage = %v; must be <= 100", lbCfg.FailurePercentageEjection.EnforcementPercentage)View on GitHub (pinned to 03255a9237)
Solutions
- Set `interval` to a non-negative Duration (omit it to accept the 10s default)
- Correct the upstream xDS/EDS resource that emitted the negative value
- Validate the LBConfig JSON against A50 ranges before handing it to ParseConfig
Example fix
// before
{"interval":"-5s","childPolicy":[{"round_robin":{}}]}
// after
{"interval":"10s","childPolicy":[{"round_robin":{}}]} Defensive patterns
Strategy: validation
Validate before calling
// Validate outlier-detection interval before ParseConfig.
var probe struct{ Interval string `json:"interval"` }
_ = json.Unmarshal(raw, &probe)
if probe.Interval != "" {
d, err := time.ParseDuration(probe.Interval)
if err != nil || d < 0 {
return fmt.Errorf("interval must be a non-negative duration, got %q", probe.Interval)
}
} Try / catch
lbCfg, err := outlierBB.ParseConfig(raw)
if err != nil {
logger.Warningf("rejecting outlier detection config: %v", err)
return fallbackLBConfig // keep prior valid config
} Prevention
- Treat all outlier-detection durations as non-negative at the source
- Omit optional duration fields to take documented defaults
- Unit-test the config emitter against A50 ranges
When it happens
Trigger: Calling ParseConfig on the `outlier_detection_experimental` balancer with JSON whose `interval` is a negative duration (e.g. "-5s") or a protobuf Duration with negative seconds. In the normal xDS path this is a redundant second check; directly it fires when a hand-built service config or a buggy resolver supplies interval < 0.
Common situations: A control-plane/EDS resource encodes a negative duration by mistake; manually constructing an outlier detection LBConfig for testing with a bad value; a protobuf Duration round-trip producing negative seconds.
Related errors
- OutlierDetectionLoadBalancingConfig.base_ejection_time = %s;
- OutlierDetectionLoadBalancingConfig.max_ejection_time = %s;
- OutlierDetectionLoadBalancingConfig.max_ejection_percent = %
- OutlierDetectionLoadBalancingConfig.SuccessRateEjection.enfo
- OutlierDetectionLoadBalancingConfig.FailurePercentageEjectio
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/b81551711d7d8964.
Report an issue: GitHub.