grpc/grpc-go · error

OutlierDetectionLoadBalancingConfig.base_ejection_time = %s;

Error message

OutlierDetectionLoadBalancingConfig.base_ejection_time = %s; must be >= 0

What it means

Returned by outlier detection ParseConfig (internal/xds/balancer/outlierdetection/balancer.go:132) when the LBConfig `base_ejection_time` Duration field is negative. Per gRFC A50 the field must be non-negative; the default is 30s when omitted. This is the same A50 non-negative check as interval, applied to the base ejection time used to compute how long an ejected endpoint stays ejected.

Source

Thrown at internal/xds/balancer/outlierdetection/balancer.go:133

	// 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)
	}
	return lbCfg, nil

View on GitHub (pinned to 03255a9237)

Solutions

  1. Set `base_ejection_time` to a non-negative Duration (omit to accept the 30s default)
  2. Fix the xDS OutlierDetection resource supplying the bad value
  3. Pre-validate durations in the config emitter

Example fix

// before
{"baseEjectionTime":"-30s"}
// after
{"baseEjectionTime":"30s"}
Defensive patterns

Strategy: validation

Validate before calling

var probe struct{ BaseEjectionTime string `json:"base_ejection_time"` }
_ = json.Unmarshal(raw, &probe)
if probe.BaseEjectionTime != "" {
    d, err := time.ParseDuration(probe.BaseEjectionTime)
    if err != nil || d < 0 {
        return fmt.Errorf("base_ejection_time must be >= 0, got %q", probe.BaseEjectionTime)
    }
}

Try / catch

lbCfg, err := outlierBB.ParseConfig(raw)
if err != nil {
    logger.Warningf("rejecting outlier detection config: %v", err)
    return fallbackLBConfig
}

Prevention

When it happens

Trigger: ParseConfig receives JSON where `base_ejection_time` decodes to a negative time.Duration (e.g. "-30s"). Fires from hand-built configs, buggy resolvers, or a control plane sending a protobuf Duration with negative seconds.

Common situations: Control-plane misconfiguration of the outlier detection policy; test fixtures with copy-pasted negative values; protobuf Duration encoding bugs producing negative seconds.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/189f35a6f8b2113b. Report an issue: GitHub.