{"record":{"id":"3ed93ab1495e18cd","repo":"grpc/grpc-go","slug":"no-subconn-is-available","errorCode":null,"errorMessage":"no SubConn is available","messagePattern":"no SubConn is available","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/balancer.go","lineNumber":268,"sourceCode":"\t// Err is the rpc error the RPC finished with. It could be nil.\n\tErr error\n\t// Trailer contains the metadata from the RPC's trailer, if present.\n\tTrailer metadata.MD\n\t// BytesSent indicates if any bytes have been sent to the server.\n\tBytesSent bool\n\t// BytesReceived indicates if any byte has been received from the server.\n\tBytesReceived bool\n\t// ServerLoad is the load received from server. It's usually sent as part of\n\t// trailing metadata.\n\t//\n\t// The only supported type now is *orca_v3.LoadReport.\n\tServerLoad any\n}\n\nvar (\n\t// ErrNoSubConnAvailable indicates no SubConn is available for pick().\n\t// gRPC will block the RPC until a new picker is available via UpdateState().\n\tErrNoSubConnAvailable = errors.New(\"no SubConn is available\")\n\t// ErrTransientFailure indicates all SubConns are in TransientFailure.\n\t// WaitForReady RPCs will block, non-WaitForReady RPCs will fail.\n\t//\n\t// Deprecated: return an appropriate error based on the last resolution or\n\t// connection attempt instead.  The behavior is the same for any non-gRPC\n\t// status error.\n\tErrTransientFailure = errors.New(\"all SubConns are in TransientFailure\")\n)\n\n// PickResult contains information related to a connection chosen for an RPC.\ntype PickResult struct {\n\t// SubConn is the connection to use for this pick, if its state is Ready.\n\t// If the state is not Ready, gRPC will block the RPC until a new Picker is\n\t// provided by the balancer (using ClientConn.UpdateState).  The SubConn\n\t// must be one returned by ClientConn.NewSubConn.\n\tSubConn SubConn\n\n\t// Done is called when the RPC is completed.  If the SubConn is not ready,","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/balancer/balancer.go#L250-L286","documentation":"Thrown by the RBAC HTTP filter builder's ParseFilterConfigOverride when the per-route override proto.Message passed by the xDS resolver is nil. The xDS HTTP filter framework requires every registered filter to handle overrides; the RBAC builder rejects nil outright rather than silently treating it as 'no override.' This prevents ambiguous state where a route reference is present in the LDS/RDS resource but carries no actual configuration payload.","triggerScenarios":"A control plane sends a RouteConfiguration (RDS) whose RouteAction references an RBACPerRoute typed per-filter-config entry, but the Any-wrapped message for that entry is nil or was stripped during proto marshalling. Also triggered if the xdsclient's unmarshalling code passes a nil override to httpfilter.ParseFilterConfigOverride due to a missing typed_config field in the per-filter-config map.","commonSituations":"Misconfigured Istio EnvoyFilter or Traffic Director route rule that specifies an RBAC per-route override key but omits the config body. Proto serialization round-trips that drop nil oneof fields. Control plane version mismatch where the per-filter-config schema expects a field the older client does not populate.","solutions":["Inspect the RDS resource for the route in question and confirm the http_filters per-filter-config entry for type envoy.extensions.filters.http.rbac.v3.RBACPerRoute has a non-nil typed_config with a valid type_url.","If no per-route RBAC override is intended for that route, remove the RBACPerRoute entry from the route's typed_per_filter_config map entirely rather than leaving a nil placeholder.","Upgrade the control plane and grpc-go to compatible xDS schema versions so the per-filter-config field is always populated with a well-formed Any."],"exampleFix":"// before (control plane route config):\nroute:\n  typed_per_filter_config:\n    \"envoy.filters.http.rbac\":\n      // missing @type body -> nil Any -> error\n\n// after:\nroute:\n  typed_per_filter_config:\n    \"envoy.filters.http.rbac\":\n      \"@type\": type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBACPerRoute\n      rbac:\n        rules:\n          action: ALLOW\n          policies:\n            allow-all:\n              permissions: [{any: true}]\n              principals: [{any: true}]","handlingStrategy":"validation","validationCode":"// Before calling the xDS filter pipeline, validate per-route override configs:\nfor routeName, route := range routeConfig.GetVirtualHosts()[0].GetRoutes() {\n    for filterName, cfg := range route.GetTypedPerFilterConfig() {\n        if strings.Contains(filterName, \"rbac\") && cfg == nil {\n            return fmt.Errorf(\"route %s has nil RBAC per-filter override\", routeName)\n        }\n        if cfg != nil && cfg.TypeUrl == \"\" {\n            return fmt.Errorf(\"route %s RBAC override has empty type_url\", routeName)\n        }\n    }\n}","typeGuard":"func isNonNilAny(msg proto.Message) bool {\n    if msg == nil {\n        return false\n    }\n    any, ok := msg.(*anypb.Any)\n    return ok && any != nil && any.TypeUrl != \"\"\n}","tryCatchPattern":null,"preventionTips":["Never leave a typed_per_filter_config entry with a nil body; either populate it fully or omit the key.","Validate all per-filter-config entries in RDS resources before applying them to the xDS client.","Use a policy-as-code tool (OPA, CedAR) to reject xDS configs with incomplete per-route overrides at deployment time."],"tags":["xds","rbac","grpc","config","proto"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}