grpc/grpc-go · error
failed to JSON marshal load balancing policy for child %q: %
Error message
failed to JSON marshal load balancing policy for child %q: %v
What it means
The cluster manager balancer handles route-action-based cluster selection (xDS RDS routing). When a child's policy type changes, it marshals the new child policy config to JSON for the gracefulswitch balancer. This error fires when that JSON marshal fails, meaning the child policy's config struct cannot be serialized. This prevents a graceful switch to the new policy for that specific child.
Source
Thrown at internal/xds/balancer/clustermanager/clustermanager.go:119
// Add new sub-balancers to the aggregator and balancergroup.
b.stateAggregator.add(childName)
b.bg.Add(childName, balancer.Get(childCfg.ChildPolicy.Name))
} else {
// If the child policy type has changed for existing sub-balancers,
// parse the new config and send down the config update to the
// balancergroup, which will take care of gracefully switching the
// child over to the new policy.
//
// If we run into errors here, we need to ensure that RPCs to this
// 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{View on GitHub (pinned to 03255a9237)
Solutions
- Enable GRPC_GO_LOG_SEVERITY=info to identify which child is failing (the child name is in the error message)
- Verify the route configuration on the management server specifies valid and complete LB policy configs for all routes
- Upgrade grpc-go to ensure all child policy config structs are compatible
- If using custom balancers, check their MarshalJSON implementation for bugs
- The error is isolated to one child — other children continue to work, so verify if the failing child's config is critical
Defensive patterns
Strategy: validation
Validate before calling
// Validate that child policy configs can marshal to JSON
// (relevant if constructing configs programmatically; normally xDS handles this)
func canMarshalChildPolicy(cfg *internalserviceconfig.BalancerConfig) bool {
_, err := cfg.MarshalJSON()
return err == nil
} Try / catch
// This error is isolated to one child; other children continue working // Monitor per-route RPC success rates to detect affected routes
Prevention
- Validate management server route configurations for valid LB policy configs
- Test route config changes in staging before production
- Keep grpc-go version current for balancer config compatibility
- Monitor per-cluster RPC success rates to detect isolated failures
When it happens
Trigger: Triggered in cluster_manager's UpdateClientConnState when a child's policy name changed and childCfg.ChildPolicy.MarshalJSON() fails. The error is scoped to one child — other children with good configs continue functioning. The child policy config comes from the xDS route configuration.
Common situations: The child policy config struct has a custom MarshalJSON that fails (programming bug in a custom balancer); the config contains an unsupported Go type that json.Marshal rejects; a version mismatch where the child policy config struct changed incompatibly; a nil or incomplete config struct passed from the xDS route configuration.
Related errors
- failed to parse load balancing policy for child %q: %v
- xds: unable to unmarshal lbconfig: %s, error: %v
- error unmarshalling xDS LB Policy: %v
- error parsing Outlier Detection config %v: %v
- failed to marshal built priority config struct into json: %v
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/0348f842c22b4cd6.
Report an issue: GitHub.