{"record":{"id":"622c0f09bffa3390","repo":"grpc/grpc-go","slug":"weighted-target-no-targets-to-pick-from","errorCode":null,"errorMessage":"weighted-target: no targets to pick from","messagePattern":"weighted-target: no targets to pick from","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/weightedtarget/weightedaggregator/aggregator.go","lineNumber":259,"sourceCode":"\t\t// need to call it when they are resumed.\n\t\twbsa.needUpdateStateOnResume = true\n\t\treturn\n\t}\n\n\twbsa.cc.UpdateState(wbsa.build())\n}\n\n// build combines sub-states into one.\n//\n// Caller must hold wbsa.mu.\nfunc (wbsa *Aggregator) build() balancer.State {\n\twbsa.logger.Infof(\"Child pickers with config: %+v\", wbsa.idToPickerState)\n\n\tif len(wbsa.idToPickerState) == 0 {\n\t\t// This is the case when all sub-balancers are removed.\n\t\treturn balancer.State{\n\t\t\tConnectivityState: connectivity.TransientFailure,\n\t\t\tPicker:            base.NewErrPicker(errors.New(\"weighted-target: no targets to pick from\")),\n\t\t}\n\t}\n\n\t// Make sure picker's return error is consistent with the aggregatedState.\n\tpickers := make([]weightedPickerState, 0, len(wbsa.idToPickerState))\n\n\tswitch aggState := wbsa.csEvltr.CurrentState(); aggState {\n\tcase connectivity.Connecting:\n\t\treturn balancer.State{\n\t\t\tConnectivityState: aggState,\n\t\t\tPicker:            base.NewErrPicker(balancer.ErrNoSubConnAvailable)}\n\tcase connectivity.TransientFailure:\n\t\t// this means that all sub-balancers are now in TransientFailure.\n\t\tfor _, ps := range wbsa.idToPickerState {\n\t\t\tpickers = append(pickers, *ps)\n\t\t}\n\t\treturn balancer.State{\n\t\t\tConnectivityState: aggState,","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/weightedtarget/weightedaggregator/aggregator.go#L241-L277","documentation":"Internal error from the weighted-target aggregator (balancer/weightedtarget/weightedaggregator/aggregator.go:255-260) returned when idToPickerState is empty — i.e. all sub-balancers (localities/targets) have been removed. The aggregator emits a TransientFailure state with a NewErrPicker wrapping this message.","triggerScenarios":"Aggregator.build() runs with len(wbsa.idToPickerState)==0. This is the case 'when all sub-balancers are removed' per the inline comment. Concretely: an xDS weighted_target/clusters update dropped every locality, or a config update cleared all weighted targets while the channel is still up.","commonSituations":"xDS management server sent a ClusterLoadAssignment / ListenersConfiguration with zero localities for the cluster; weighted-target config object has an empty targets map; transient control-plane state during a rolling update removing all endpoints; misconfigured traffic splitting with no fallback locality.","solutions":["Inspect the xDS / weighted-target config in the control plane: the targets map must contain at least one locality with weight > 0.","If sub-balancers are intentionally removable, expect TransientFailure and either fail over to another channel or wait for the next config update (use grpc.WaitForReady(true)).","Verify the parent (cluster_resolver / xds) is forwarding the right weighted-target config and not an empty one during reconciliation.","Check channelz for the weighted_target balancer children to confirm which localities were present before removal."],"exampleFix":"// before — weighted_target config with no targets\n{\n  \"targets\": {},            // -> 'weighted-target: no targets to pick from'\n  \"targetsFieldCase\": \"targets\"\n}\n\n// after — provide at least one locality\n{\n  \"targets\": {\n    \"loc1\": { \"weight\": 1, \"childPolicy\": [{\"round_robin\": {}}] }\n  }\n}","handlingStrategy":"validation","validationCode":"// Validate weighted-target config has at least one target\nfunc validateWT(cfg *weightedtargetConfig) error {\n    if len(cfg.Targets) == 0 {\n        return errors.New(\"weighted-target: no targets configured\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"weighted-target: no targets to pick from\") {\n    // control plane delivered an empty locality set; fail over or wait\n}","preventionTips":["Keep at least one fallback locality (weight>0) in xDS weighted_target config.","Monitor CDS/EDS for empty cluster assignments during deploys.","Prefer a cluster_resolver/round_robin fallback when weighted_target could go empty."],"tags":["weighted-target","balancer","xds","grpc-go"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}