grpc/grpc-go · error
bad resolver state
Error message
bad resolver state
What it means
Thrown when the *anypb.Any override payload fails to unmarshal into *rpb.RBACPerRoute via UnmarshalTo. This means the type_url and/or the serialized bytes inside the Any do not correspond to a valid RBACPerRoute proto message — the wire payload is corrupt, truncated, or contains a different message type than advertised.
Solutions
- Verify the Any's type_url is exactly type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBACPerRoute and the payload bytes are a serialized RBACPerRoute (which wraps an RBAC message in its 'rbac' field), not a bare RBAC.
- Align the go-control-plane version used by the control plane with the one linked into grpc-go on the client so the proto schemas match.
- Capture the full DiscoveryResponse from the control plane (e.g., via GRPC_XDS_DEBUG_V3=log) and validate the bytes deserialize standalone with protoc --decode_raw.
Example fix
// before: control plane puts a bare RBAC into the per-route override
override_any, _ := anypb.New(&v3rbacpb.RBAC{Rules: rules})
// after: wrap it in RBACPerRoute as the schema requires
override_any, _ := anypb.New(&rpb.RBACPerRoute{Rbac: &v3rbacpb.RBAC{Rules: rules}}) Defensive patterns
Strategy: validation
Validate before calling
// Validate the Any can unmarshal into RBACPerRoute before calling ParseFilterConfigOverride:
func validateRBACOverride(any *anypb.Any) error {
expectedURL := "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBACPerRoute"
if any.TypeUrl != expectedURL {
return fmt.Errorf("type_url mismatch: want %s, got %s", expectedURL, any.TypeUrl)
}
msg := new(rpb.RBACPerRoute)
if err := any.UnmarshalTo(msg); err != nil {
return fmt.Errorf("payload does not unmarshal to RBACPerRoute: %w", err)
}
return nil
} Try / catch
// When constructing the chain engine from xDS, catch unmarshal failures and NACK:
cfg, err := b.ParseFilterConfigOverride(overrideAny)
if err != nil {
return fmt.Errorf("rejecting xDS resource: RBAC override parse failed: %w", err)
} Prevention
- Pin go-control-plane to the same version on control plane and data plane.
- Run proto round-trip tests: marshal RBACPerRoute to Any, unmarshal back, assert equality.
- Use xDS debug logging (GRPC_XDS_DEBUG_V3=log) to inspect DiscoveryResponses before they reach filter builders.
When it happens
Trigger: The Any's type_url is set to RBACPerRoute but the bytes were serialized from a different proto (e.g., an RBAC message instead of RBACPerRoute). A truncated or corrupted protobuf payload reaching the filter after a buggy control-plane serialization. A schema version mismatch where the control plane serializes a newer RBACPerRoute field layout that the client's go-control-plane version cannot decode.
Common situations: Upgrading Envoy/go-control-plane on the control plane to a version that added new required fields to RBACPerRoute without upgrading grpc-go on the data plane. A network-level or serialization-level corruption of the LDS/RDS DiscoveryResponse. A control plane that mistakenly puts an RBAC (not RBACPerRoute) message inside the per-route override Any.
Related errors
- all SubConns are in TransientFailure
- grpc: credentials.Bundle may not be used with individual…
- grpc: the credentials require transport level security (use…
- no SubConn is available
- produced zero addresses
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/ef1772e20a9c89b1.
Report an issue: GitHub.
Appendix: source
Thrown at balancer/balancer.go:394
type ExitIdler interface {
// ExitIdle instructs the LB policy to reconnect to backends / exit the
// IDLE state, if appropriate and possible. Note that SubConns that enter
// the IDLE state will not reconnect until SubConn.Connect is called.
ExitIdle()
}
// ClientConnState describes the state of a ClientConn relevant to the
// balancer.
type ClientConnState struct {
ResolverState resolver.State
// The parsed load balancing configuration returned by the builder's
// ParseConfig method, if implemented.
BalancerConfig serviceconfig.LoadBalancingConfig
}
// ErrBadResolverState may be returned by UpdateClientConnState to indicate a
// problem with the provided name resolver data.
var ErrBadResolverState = errors.New("bad resolver state")
View on GitHub (pinned to 0c51461d27)