grpc/grpc-go · error
xds: unable to unmarshal LBconfig: %s, error: %v
Error message
xds: unable to unmarshal LBconfig: %s, error: %v
What it means
The outlier detection balancer's ParseConfig unmarshals the raw JSON into an LBConfig struct with fields for interval, base_ejection_time, max_ejection_time, max_ejection_percent, and sub-configs for success-rate ejection (sre) and failure-percentage ejection (fpe). This error fires when the JSON is syntactically invalid or field types are wrong. Outlier detection implements adaptive circuit-breaking based on backend health metrics.
Source
Thrown at internal/xds/balancer/outlierdetection/balancer.go:112
b.logger.Infof("Created")
b.child = synchronizingBalancerWrapper{lb: gracefulswitch.NewBalancer(b, bOpts)}
go b.run()
return b
}
func (bb) ParseConfig(s json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
lbCfg := &LBConfig{
// Default top layer values as documented in A50.
Interval: iserviceconfig.Duration(10 * time.Second),
BaseEjectionTime: iserviceconfig.Duration(30 * time.Second),
MaxEjectionTime: iserviceconfig.Duration(300 * time.Second),
MaxEjectionPercent: 10,
}
// This unmarshalling handles underlying layers sre and fpe which have their
// own defaults for their fields if either sre or fpe are present.
if err := json.Unmarshal(s, lbCfg); err != nil { // Validates child config if present as well.
return nil, fmt.Errorf("xds: unable to unmarshal LBconfig: %s, error: %v", string(s), err)
}
// 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:View on GitHub (pinned to 03255a9237)
Solutions
- Inspect the raw JSON in the error message (it's included as %s) to identify the specific malformation
- Verify field names match the protobuf JSON mapping: interval, baseEjectionTime, maxEjectionTime, maxEjectionPercent, childPolicy, successRateEjection, failurePercentageEjection
- Ensure duration fields are strings in Go duration format (e.g., "10s", "30s") and numeric fields are numbers
- Verify the management server's outlier detection configuration matches gRFC A50
- If the error comes from manual ParseConfig calls, validate the JSON schema against the expected format
Example fix
// before: malformed outlier detection config with wrong types
{"interval": 10, "maxEjectionPercent": "10"}
// after: correct types (duration as string, percent as number)
{"interval": "10s", "maxEjectionPercent": 10} Defensive patterns
Strategy: validation
Validate before calling
// Validate outlier detection config JSON before passing to ParseConfig
func validateOutlierDetectionConfig(raw json.RawMessage) error {
var cfg struct {
Interval json.Number `json:"interval"`
BaseEjectionTime json.Number `json:"baseEjectionTime"`
MaxEjectionTime json.Number `json:"maxEjectionTime"`
MaxEjectionPercent json.Number `json:"maxEjectionPercent"`
}
if err := json.Unmarshal(raw, &cfg); err != nil {
return fmt.Errorf("invalid outlier detection JSON: %w", err)
}
return nil
} Type guard
// Type guard for parsed outlier detection config
func isOutlierDetectionConfig(cfg serviceconfig.LoadBalancingConfig) bool {
_, ok := cfg.(*outlierdetection.LBConfig)
return ok
} Prevention
- Validate outlier detection JSON configs for correct types: durations as strings, percentages as numbers
- Verify field names match protobuf JSON mapping (interval, baseEjectionTime, maxEjectionTime, maxEjectionPercent)
- Test outlier detection configs from the management server against gRFC A50
- Keep grpc-go version current for outlier detection config schema compatibility
When it happens
Trigger: Triggered when the outlier detection balancer's ParseConfig is called (from xDS or directly) and json.Unmarshal fails on the raw JSON. In the xDS flow, the CDS balancer calls this with the outlier detection JSON from the cluster resource. The struct has specific defaults and validation for duration fields and numeric ranges.
Common situations: The management server sends malformed outlier detection JSON with wrong field types (e.g., string for a numeric field); the JSON uses incorrect field names or nesting; a protobuf-to-JSON serialization issue on the server produces structurally invalid JSON; a version mismatch where field names changed between protocol versions.
Related errors
- xds: unable to unmarshal lbconfig: %s, error: %v
- failed to correctly update Outlier Detection config %v
- error parsing Outlier Detection config %v: %v
- no priority is provided, all priorities are removed
- xds_wrr_locality: invalid LBConfig: child policy field must
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/d2410ca77bfbc5a9.
Report an issue: GitHub.