grpc/grpc-go · error
wrr: errorUtilizationPenalty must be non-negative
Error message
wrr: errorUtilizationPenalty must be non-negative
What it means
The weighted_round_robin (WRR) load balancer validates its service config inside ParseConfig (balancer.go:133). errorUtilizationPenalty is a float64 that scales how much an endpoint's weight is reduced for its error rate (weight = rps/(utilization + errorRate*penalty)). A negative value is rejected because it would make error-prone endpoints appear MORE attractive, inverting the load-balancing intent. The default is 1.0.
Source
Thrown at balancer/weightedroundrobin/balancer.go:134
}
return b
}
func (bb) ParseConfig(js json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
lbCfg := &lbConfig{
// Default values as documented in A58.
OOBReportingPeriod: iserviceconfig.Duration(10 * time.Second),
BlackoutPeriod: iserviceconfig.Duration(10 * time.Second),
WeightExpirationPeriod: iserviceconfig.Duration(3 * time.Minute),
WeightUpdatePeriod: iserviceconfig.Duration(time.Second),
ErrorUtilizationPenalty: 1,
}
if err := json.Unmarshal(js, lbCfg); err != nil {
return nil, fmt.Errorf("wrr: unable to unmarshal LB policy config: %s, error: %v", string(js), err)
}
if lbCfg.ErrorUtilizationPenalty < 0 {
return nil, fmt.Errorf("wrr: errorUtilizationPenalty must be non-negative")
}
// For easier comparisons later, ensure the OOB reporting period is unset
// (0s) when OOB reports are disabled.
if !lbCfg.EnableOOBLoadReport {
lbCfg.OOBReportingPeriod = 0
}
// Impose lower bound of 100ms on weightUpdatePeriod.
if !internal.AllowAnyWeightUpdatePeriod && lbCfg.WeightUpdatePeriod < iserviceconfig.Duration(100*time.Millisecond) {
lbCfg.WeightUpdatePeriod = iserviceconfig.Duration(100 * time.Millisecond)
}
return lbCfg, nil
}
func (bb) Name() string {
return NameView on GitHub (pinned to 03255a9237)
Solutions
- Set errorUtilizationPenalty to 0 or a positive number (e.g. 1.0) in the service config JSON, or omit the field to use the default 1.0.
- If the config comes from xDS, fix the value at the control plane / management server and re-push.
- Validate the LB config JSON with a schema or a dry-run parse before applying it to a live channel.
Example fix
// before
{"loadBalancingConfig":{"weighted_round_robin":{"errorUtilizationPenalty":-0.5}}}
// after
{"loadBalancingConfig":{"weighted_round_robin":{"errorUtilizationPenalty":1.0}}} Defensive patterns
Strategy: validation
Validate before calling
// Validate before applying service config JSON for weighted_round_robin.
func validateWRRCfg(js []byte) error {
cfg := struct{ ErrorUtilizationPenalty *float64 `json:"errorUtilizationPenalty"` }{}
if err := json.Unmarshal(js, &cfg); err != nil { return err }
if cfg.ErrorUtilizationPenalty != nil && *cfg.ErrorUtilizationPenalty < 0 {
return fmt.Errorf("errorUtilizationPenalty must be >= 0, got %v", *cfg.ErrorUtilizationPenalty)
}
return nil
} Prevention
- Treat errorUtilizationPenalty as an unsigned scaling factor; never compute it from a subtraction that can go negative.
- Run the service config JSON through your schema/validator before pushing to xDS or WithDefaultServiceConfig.
- Unit-test ParseConfig-equivalent validation against boundary values (0, negative, large).
When it happens
Trigger: Setting "errorUtilizationPenalty" to a negative number in the JSON config for the weighted_round_robin LB policy — via a service config file, xDS control plane, or the WithDefaultServiceConfig / defaultServiceConfigRawJSON dial option. ParseConfig calls json.Unmarshal then checks lbCfg.ErrorUtilizationPenalty < 0.
Common situations: A hand-written service config JSON with a stray minus sign or typo; an xDS management server pushing an out-of-range value; copy-pasting an OOB reporting template and editing the penalty incorrectly.
Related errors
- randomsubsetting: json.Unmarshal failed for configuration: %
- randomsubsetting: SubsetSize must be greater than 0
- randomsubsetting: ChildPolicy must be specified
- min_ring_size value of %d is greater than max supported valu
- max_ring_size value of %d is greater than max supported valu
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/60011aacd3cc7bf4.
Report an issue: GitHub.