{"record":{"id":"23f76a9165f9786d","repo":"grpc/grpc-go","slug":"failed-to-parse-load-balancing-policy-for-child-q","errorCode":null,"errorMessage":"failed to parse load balancing policy for child %q: %v","messagePattern":"failed to parse load balancing policy for child %q: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/balancer/clustermanager/clustermanager.go","lineNumber":129,"sourceCode":"\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{\n\t\t\t\tEndpoints:     endpointsSplit[childName],\n\t\t\t\tServiceConfig: s.ResolverState.ServiceConfig,\n\t\t\t\tAttributes:    s.ResolverState.Attributes,\n\t\t\t},\n\t\t\tBalancerConfig: lbCfg,\n\t\t}); err != nil {\n\t\t\tretErr = fmt.Errorf(\"failed to push new configuration %v to child %q: %v\", childCfg.ChildPolicy.Config, childName, err)\n\t\t\tb.setErrorPickerForChild(childName, retErr)\n\t\t}\n","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/balancer/clustermanager/clustermanager.go#L111-L147","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Catch the parse failure and treat the named child as broken.\nif err := cm.UpdateClientConnState(state); err != nil {\n    if strings.Contains(err.Error(), \"failed to parse load balancing policy for child\") {\n        // isolate the failing child; other children keep serving\n    }\n}","preventionTips":["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."],"tags":["go","grpc","xds","balancer","json","parse","clustermanager"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}