grpc/grpc-go · error

no children to pick from

Error message

no children to pick from

What it means

Thrown by ParseFilterConfig when the proto.Message for the Router filter is non-nil but is not *anypb.Any. The xDS framework always encodes filter configs as *anypb.Any; receiving another type signals a caller bug or a proto type mismatch between the framework and the filter builder.

Solutions

  1. Always pass *anypb.Any to ParseFilterConfig — wrap with anypb.New(&pb.Router{}).
  2. Ensure all proto imports use google.golang.org/protobuf/types/known/anypb consistently; avoid mixing github.com/golang/protobuf/ptypes/any.
  3. If the error comes from production xDS flow, verify the grpc-go module version is uniform across the build (go mod why google.golang.org/grpc).

Example fix

// before:
cfg, err := b.ParseFilterConfig(&pb.Router{})

// after:
any, _ := anypb.New(&pb.Router{})
cfg, err := b.ParseFilterConfig(any)
Defensive patterns

Strategy: type-guard

Validate before calling

// Ensure cfg is *anypb.Any before dispatching to ParseFilterConfig:
func safeParseConfig(b httpfilter.Builder, cfg proto.Message) (httpfilter.FilterConfig, error) {
    any, ok := cfg.(*anypb.Any)
    if !ok {
        return nil, fmt.Errorf("expected *anypb.Any, got %T", cfg)
    }
    return b.ParseFilterConfig(any)
}

Type guard

func isAnypbAny(msg proto.Message) bool {
    _, ok := msg.(*anypb.Any)
    return ok
}

Prevention

When it happens

Trigger: A custom httpfilter dispatch path or test harness passes a *pb.Router directly to ParseFilterConfig instead of wrapping it in *anypb.Any. A grpc-go fork changed the httpfilter.Builder interface contract. Proto import path divergence causes the anypb.Any type seen by the builder to differ from the one passed.

Common situations: Unit tests of the xdsclient filter unmarshalling that construct filter configs without anypb.New. A mixed-dependency build where google.golang.org/protobuf and github.com/golang/protobuf Any types are interchanged. An internal refactor that bypasses the standard Any wrapping.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/3f5dc3ba51a464f1. Report an issue: GitHub.

Appendix: source

Thrown at balancer/endpointsharding/endpointsharding.go:293

	// the aggregated state, use the pickers present that are currently in that
	// state only.
	var aggState connectivity.State
	var pickers []balancer.Picker
	if len(readyPickers) >= 1 {
		aggState = connectivity.Ready
		pickers = readyPickers
	} else if len(connectingPickers) >= 1 {
		aggState = connectivity.Connecting
		pickers = connectingPickers
	} else if len(idlePickers) >= 1 {
		aggState = connectivity.Idle
		pickers = idlePickers
	} else if len(transientFailurePickers) >= 1 {
		aggState = connectivity.TransientFailure
		pickers = transientFailurePickers
	} else {
		aggState = connectivity.TransientFailure
		pickers = []balancer.Picker{base.NewErrPicker(errors.New("no children to pick from"))}
	} // No children (resolver error before valid update).
	p := &pickerWithChildStates{
		pickers:     pickers,
		childStates: childStates,
		next:        uint32(randIntN(len(pickers))),
	}
	es.cc.UpdateState(balancer.State{
		ConnectivityState: aggState,
		Picker:            p,
	})
}

// pickerWithChildStates delegates to the pickers it holds in a round robin
// fashion. It also contains the childStates of all the endpointSharding's
// children.
type pickerWithChildStates struct {
	pickers     []balancer.Picker
	childStates []ChildState

View on GitHub (pinned to 0c51461d27)