{"record":{"id":"72c3d115f197225b","repo":"grpc/grpc-go","slug":"error-unmarshalling-xds-lb-policy-v","errorCode":null,"errorMessage":"error unmarshalling xDS LB Policy: %v","messagePattern":"error unmarshalling xDS LB Policy: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/balancer/cdsbalancer/cdsbalancer.go","lineNumber":256,"sourceCode":"\t\tp := b.updatePriorityConfig(clusterName, &clusterConfig)\n\t\tnewPriorities = append(newPriorities, p)\n\tcase xdsresource.ClusterTypeAggregate:\n\t\tfor _, leaf := range clusterConfig.AggregateConfig.LeafClusters {\n\t\t\tleafCluster := b.clusterConfigs[leaf]\n\t\t\t// Update priority config for leaf clusters.\n\t\t\tp := b.updatePriorityConfig(leaf, &leafCluster.Config)\n\t\t\tnewPriorities = append(newPriorities, p)\n\t\t}\n\t}\n\tb.priorities = newPriorities\n\n\tif err := b.updateOutlierDetection(); err != nil {\n\t\treturn b.annotateErrorWithNodeID(fmt.Errorf(\"failed to correctly update Outlier Detection config %v\", err))\n\t}\n\n\t// The LB policy is configured by the root cluster.\n\tif err := json.Unmarshal(clusterConfig.Cluster.LBPolicy, &b.xdsLBPolicy); err != nil {\n\t\treturn b.annotateErrorWithNodeID(fmt.Errorf(\"error unmarshalling xDS LB Policy: %v\", err))\n\t}\n\tif err := b.updateChildConfig(); err != nil {\n\t\treturn b.annotateErrorWithNodeID(err)\n\t}\n\treturn nil\n}\n\n// updateChildConfig builds child policy configuration using endpoint addresses\n// returned from the XDSConfig and child policy configuration.\n//\n// A child policy is created if one doesn't already exist. The newly built\n// configuration is then pushed to the child policy.\nfunc (b *cdsBalancer) updateChildConfig() error {\n\tif b.childLB == nil {\n\t\tchildLB, err := newChildBalancer(b.cc, b.bOpts)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create child policy of type %s: %v\", priority.Name, err)\n\t\t}","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/balancer/cdsbalancer/cdsbalancer.go#L238-L274","documentation":"Returned by handleClusterUpdate (line 256, wrapped via annotateErrorWithNodeID) when json.Unmarshal fails on clusterConfig.Cluster.LBPolicy (a json.RawMessage from the CDS cluster resource) into b.xdsLBPolicy (an internalserviceconfig.BalancerConfig). The %v is the JSON unmarshalling error. This means the LB policy field in the cluster resource contains malformed or structurally incompatible JSON.","triggerScenarios":"The management server's CDS response includes a cluster with an LB policy field (typically {\"xds_wrr_locality\":{}} or {\"ring_hash\":{}}) that does not match the BalancerConfig struct shape. This fires after the cluster resource is accepted but before child config is built.","commonSituations":"Management server sends an unrecognized or malformed LB policy JSON in the cluster resource. Version skew: the server sends a new LB policy format the client does not understand. A control plane bug producing invalid JSON in the LBPolicy field. The LB policy field is present but empty or not a valid JSON object.","solutions":["Inspect the CDS resource's lb_policy field in the management server config and validate it is a recognized policy name (round_robin, ring_hash, xds_wrr_locality, least_request).","Check for version compatibility between the client grpc-go version and the control plane — newer LB policies may not be supported by older clients.","Enable xDS debug logging and look at the pretty-printed cluster resource to see the raw LBPolicy bytes.","Update the client to a grpc-go version that supports the LB policy the server is configuring."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// If you control the cluster resource, validate the LB policy JSON\n// before sending it via CDS:\nfunc validateLBPolicy(raw json.RawMessage) error {\n    var cfg internalserviceconfig.BalancerConfig\n    if err := json.Unmarshal(raw, &cfg); err != nil {\n        return fmt.Errorf(\"invalid LB policy JSON: %w\", err)\n    }\n    validPolicies := map[string]bool{\n        \"round_robin\": true, \"ring_hash\": true,\n        \"xds_wrr_locality\": true, \"least_request\": true,\n    }\n    if !validPolicies[cfg.Name] {\n        return fmt.Errorf(\"unsupported LB policy: %s\", cfg.Name)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Channel will enter TRANSIENT_FAILURE. Monitor and inspect logs:\nif conn.GetState() == connectivity.TransientFailure {\n    // grep logs for 'error unmarshalling xDS LB Policy'\n    // the %v shows the JSON error pointing to the bad field\n}","preventionTips":["Use only documented, client-supported LB policies in the management server cluster config.","Version-check the client grpc-go release notes for newly supported LB policies.","Test cluster resources in staging before production rollout."],"tags":["xds","lb-policy","json","cds","config"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}