grpc/grpc-go · error
weighted-target: no targets to pick from
Error message
weighted-target: no targets to pick from
What it means
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.
Source
Thrown at balancer/weightedtarget/weightedaggregator/aggregator.go:259
// need to call it when they are resumed.
wbsa.needUpdateStateOnResume = true
return
}
wbsa.cc.UpdateState(wbsa.build())
}
// build combines sub-states into one.
//
// Caller must hold wbsa.mu.
func (wbsa *Aggregator) build() balancer.State {
wbsa.logger.Infof("Child pickers with config: %+v", wbsa.idToPickerState)
if len(wbsa.idToPickerState) == 0 {
// This is the case when all sub-balancers are removed.
return balancer.State{
ConnectivityState: connectivity.TransientFailure,
Picker: base.NewErrPicker(errors.New("weighted-target: no targets to pick from")),
}
}
// Make sure picker's return error is consistent with the aggregatedState.
pickers := make([]weightedPickerState, 0, len(wbsa.idToPickerState))
switch aggState := wbsa.csEvltr.CurrentState(); aggState {
case connectivity.Connecting:
return balancer.State{
ConnectivityState: aggState,
Picker: base.NewErrPicker(balancer.ErrNoSubConnAvailable)}
case connectivity.TransientFailure:
// this means that all sub-balancers are now in TransientFailure.
for _, ps := range wbsa.idToPickerState {
pickers = append(pickers, *ps)
}
return balancer.State{
ConnectivityState: aggState,View on GitHub (pinned to 03255a9237)
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.
Example fix
// before — weighted_target config with no targets
{
"targets": {}, // -> 'weighted-target: no targets to pick from'
"targetsFieldCase": "targets"
}
// after — provide at least one locality
{
"targets": {
"loc1": { "weight": 1, "childPolicy": [{"round_robin": {}}] }
}
} Defensive patterns
Strategy: validation
Validate before calling
// Validate weighted-target config has at least one target
func validateWT(cfg *weightedtargetConfig) error {
if len(cfg.Targets) == 0 {
return errors.New("weighted-target: no targets configured")
}
return nil
} Try / catch
if strings.Contains(err.Error(), "weighted-target: no targets to pick from") {
// control plane delivered an empty locality set; fail over or wait
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- no SubConn is available
- all SubConns are in TransientFailure
- bad resolver state
- no children to pick from
- no priority is provided, all priorities are removed
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/622c0f09bffa3390.
Report an issue: GitHub.