grpc/grpc-go · error
failed to parse load balancing policy for child
Error message
failed to parse load balancing policy for child %q: %v
What it means
After successfully marshaling a child policy config to JSON during a type change, cluster_manager hands the bytes to balancergroup.ParseConfig (clustermanager.go:127-132). ParseConfig wraps the JSON in gracefulswitch format; if it rejects the bytes (wrong top-level shape, unknown policy, missing fields), the error is wrapped and an error picker is set for that child only.
Solutions
- Compare the marshaled JSON to what balancergroup.ParseConfig expects (a one-element array of {policyName: {...}}).
- Update the child balancer package to a version whose MarshalJSON output is gracefulswitch-compatible.
- Use channelz logs to inspect the exact bytes that failed parsing.
Defensive patterns
Strategy: try-catch
Try / catch
// Catch the parse failure and treat the named child as broken.
if err := cm.UpdateClientConnState(state); err != nil {
if strings.Contains(err.Error(), "failed to parse load balancing policy for child") {
// isolate the failing child; other children keep serving
}
} Prevention
- Round-trip test each child policy's MarshalJSON -> balancergroup.ParseConfig before deployment.
- Pin the child balancer package version compatible with balancergroup.
- Inspect channelz for the exact bytes that failed parsing.
When it happens
Trigger: childCfg.ChildPolicy.MarshalJSON produces JSON that balancergroup.ParseConfig rejects (e.g. not a single-element [{name: config}] array, or a policy name balancergroup cannot resolve).
Common situations: A child policy whose JSON output does not match what gracefulswitch expects; control plane sends a config that round-trips incorrectly through the child policy's parser; version drift between gRPC core and the child balancer package.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to JSON marshal load balancing policy for child
- failed to push new configuration
- unexpected balancer config with type: %T
- xds: unable to unmarshal LBconfig
- child policy not registered
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/23f76a9165f9786d.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/balancer/clustermanager/clustermanager.go:129
// child fail, while RPCs to other children with good configs
// continue to succeed.
newPolicyName, oldPolicyName := childCfg.ChildPolicy.Name, b.children[childName].ChildPolicy.Name
if newPolicyName != oldPolicyName {
var err error
var cfgJSON []byte
cfgJSON, err = childCfg.ChildPolicy.MarshalJSON()
if err != nil {
retErr = fmt.Errorf("failed to JSON marshal load balancing policy for child %q: %v", childName, err)
b.setErrorPickerForChild(childName, retErr)
continue
}
// This overwrites lbCfg to be in the format expected by the
// gracefulswitch balancer. So, when this config is pushed to
// the child (below), it will result in a graceful switch to the
// new child policy.
lbCfg, err = balancergroup.ParseConfig(cfgJSON)
if err != nil {
retErr = fmt.Errorf("failed to parse load balancing policy for child %q: %v", childName, err)
b.setErrorPickerForChild(childName, retErr)
continue
}
}
}
if err := b.bg.UpdateClientConnState(childName, balancer.ClientConnState{
ResolverState: resolver.State{
Endpoints: endpointsSplit[childName],
ServiceConfig: s.ResolverState.ServiceConfig,
Attributes: s.ResolverState.Attributes,
},
BalancerConfig: lbCfg,
}); err != nil {
retErr = fmt.Errorf("failed to push new configuration %v to child %q: %v", childCfg.ChildPolicy.Config, childName, err)
b.setErrorPickerForChild(childName, retErr)
}
View on GitHub (pinned to 0c51461d27)