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

  1. Enable GRPC_GO_LOG_SEVERITY=info to identify which child is failing (the child name is in the error message)
  2. Verify the route configuration on the management server specifies valid and complete LB policy configs for all routes
  3. Upgrade grpc-go to ensure all child policy config structs are compatible
  4. If using custom balancers, check their MarshalJSON implementation for bugs
  5. 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

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


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