grpc/grpc-go · error
weighted-target: no targets to pick from
Error message
weighted-target: no targets to pick from
What it means
Thrown by StringMatcherFromProto in its default switch case when the StringMatcher proto's MatchPattern oneof is set to a variant that the library does not recognize. As of the current code, the handled variants are Exact, Prefix, Suffix, SafeRegex, and Contains. Any other oneof variant (or a nil match pattern with a new proto field) falls through to this error.
Solutions
- Upgrade grpc-go (and its bundled go-control-plane dependency) to a version whose StringMatcherFromProto handles the variant the control plane sends.
- Downgrade or patch the control plane to only use supported StringMatcher variants: exact, prefix, suffix, safe_regex, or contains.
- File an issue / contribute a case to StringMatcherFromProto for the new variant if it is part of the upstream proto spec.
Example fix
// before: control plane sends a new matcher variant not yet supported string_matcher: some_new_match_type: "value" // after: use a supported variant string_matcher: exact: "value"
Defensive patterns
Strategy: validation
Validate before calling
// Check that the StringMatcher uses a known variant before constructing:
func validateStringMatcherProto(sm *v3matcherpb.StringMatcher) error {
switch sm.GetMatchPattern().(type) {
case *v3matcherpb.StringMatcher_Exact,
*v3matcherpb.StringMatcher_Prefix,
*v3matcherpb.StringMatcher_Suffix,
*v3matcherpb.StringMatcher_SafeRegex,
*v3matcherpb.StringMatcher_Contains:
return nil
default:
return fmt.Errorf("unsupported StringMatcher variant: %T", sm.GetMatchPattern())
}
} Type guard
func isSupportedStringMatcher(sm *v3matcherpb.StringMatcher) bool {
switch sm.GetMatchPattern().(type) {
case *v3matcherpb.StringMatcher_Exact,
*v3matcherpb.StringMatcher_Prefix,
*v3matcherpb.StringMatcher_Suffix,
*v3matcherpb.StringMatcher_SafeRegex,
*v3matcherpb.StringMatcher_Contains:
return true
}
return false
} Prevention
- Pin go-control-plane versions so the StringMatcher proto does not introduce unknown variants.
- When upgrading go-control-plane, grep StringMatcherFromProto for new case branches and add them.
- Use only the five canonical StringMatcher variants in control-plane templates.
When it happens
Trigger: A future or custom go-control-plane version adds a new StringMatcher variant (e.g., a hypothetical 'glob' type) and the control plane sends it, but grpc-go's StringMatcherFromProto was compiled against an older proto that does not have a case for it. The switch falls through to default.
Common situations: Version skew: the control plane uses a newer envoy.type.matcher.v3.StringMatcher proto with additional match pattern variants. A custom or patched go-control-plane that adds non-standard oneof fields. A proto deserialization quirk where GetMatchPattern() returns a type the switch does not enumerate.
Related errors
- unknown header matcher type
- all SubConns are in TransientFailure
- ALTS: untrusted platform. ALTS is only supported on GCP
- bad resolver state
- client-side auth info is not of type alts.AuthInfo
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/622c0f09bffa3390.
Report an issue: GitHub.
Appendix: 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 0c51461d27)