{"record":{"id":"0348f842c22b4cd6","repo":"grpc/grpc-go","slug":"failed-to-json-marshal-load-balancing-policy-for-c","errorCode":null,"errorMessage":"failed to JSON marshal load balancing policy for child %q: %v","messagePattern":"failed to JSON marshal load balancing policy for child %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/balancer/clustermanager/clustermanager.go","lineNumber":119,"sourceCode":"\t\t\t// Add new sub-balancers to the aggregator and balancergroup.\n\t\t\tb.stateAggregator.add(childName)\n\t\t\tb.bg.Add(childName, balancer.Get(childCfg.ChildPolicy.Name))\n\t\t} else {\n\t\t\t// If the child policy type has changed for existing sub-balancers,\n\t\t\t// parse the new config and send down the config update to the\n\t\t\t// balancergroup, which will take care of gracefully switching the\n\t\t\t// child over to the new policy.\n\t\t\t//\n\t\t\t// If we run into errors here, we need to ensure that RPCs to this\n\t\t\t// child fail, while RPCs to other children with good configs\n\t\t\t// continue to succeed.\n\t\t\tnewPolicyName, oldPolicyName := childCfg.ChildPolicy.Name, b.children[childName].ChildPolicy.Name\n\t\t\tif newPolicyName != oldPolicyName {\n\t\t\t\tvar err error\n\t\t\t\tvar cfgJSON []byte\n\t\t\t\tcfgJSON, err = childCfg.ChildPolicy.MarshalJSON()\n\t\t\t\tif err != nil {\n\t\t\t\t\tretErr = fmt.Errorf(\"failed to JSON marshal load balancing policy for child %q: %v\", childName, err)\n\t\t\t\t\tb.setErrorPickerForChild(childName, retErr)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// This overwrites lbCfg to be in the format expected by the\n\t\t\t\t// gracefulswitch balancer. So, when this config is pushed to\n\t\t\t\t// the child (below), it will result in a graceful switch to the\n\t\t\t\t// new child policy.\n\t\t\t\tlbCfg, err = balancergroup.ParseConfig(cfgJSON)\n\t\t\t\tif err != nil {\n\t\t\t\t\tretErr = fmt.Errorf(\"failed to parse load balancing policy for child %q: %v\", childName, err)\n\t\t\t\t\tb.setErrorPickerForChild(childName, retErr)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif err := b.bg.UpdateClientConnState(childName, balancer.ClientConnState{\n\t\t\tResolverState: resolver.State{","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/balancer/clustermanager/clustermanager.go#L101-L137","documentation":"When a child policy's type changes in cluster_manager (clustermanager.go:113-122), the new ChildPolicy must be re-serialized to JSON so balancergroup.ParseConfig can drive a graceful switch. If childCfg.ChildPolicy.MarshalJSON fails, cluster_manager records the error, installs an error picker for that one child via setErrorPickerForChild, and continues processing the rest. Only RPCs routed to the affected child fail.","triggerScenarios":"childCfg.ChildPolicy.Config holds a json.RawMessage with corrupt/invalid bytes, or a custom ChildPolicy type whose MarshalJSON returns an error during the policy-type-change path (newPolicyName != oldPolicyName).","commonSituations":"Hand-crafted ChildPolicy.Config with invalid raw JSON bytes; bug in a custom child balancer's MarshalJSON; rare race in xDS resource translation producing malformed raw messages.","solutions":["Inspect the raw bytes of ChildPolicy.Config for malformed JSON before deployment.","If using a custom balancer, ensure MarshalJSON never errors on valid in-memory configs.","Treat this child as broken: cluster_manager isolates the failure, so other children keep serving while you fix the source."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// UpdateClientConnState on cluster_manager returns the wrapped error; isolate per-child failures.\nif err := cm.UpdateClientConnState(state); err != nil {\n    if strings.Contains(err.Error(), \"failed to JSON marshal load balancing policy for child\") {\n        // log the child name from the error, continue serving other children\n    }\n}","preventionTips":["Validate that every ChildPolicy.Config is valid JSON before sending it to cluster_manager.","For custom child balancers, ensure MarshalJSON never errors on in-memory configs.","Use channelz to correlate which child failed."],"tags":["go","grpc","xds","balancer","json","clustermanager"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}