grpc/grpc-go · error
produced zero addresses
Error message
produced zero addresses
What it means
Thrown by ParseFilterConfigOverride on the Router filter when a non-nil per-route override is provided. The gRPC Router filter is purely a marker/terminal filter — it does not support any per-route configuration overrides. Envoy's router filter has per-route options, but gRPC's implementation intentionally rejects them.
Source
Thrown at balancer/ringhash/ringhash.go:299
}
if idleBalancer != nil {
idleBalancer.ExitIdle()
}
}
if b.inhibitChildUpdates {
return
}
// Update the channel.
if b.endpointStates.Len() > 0 && b.shouldRegenerateRing {
// with a non-empty list of endpoints.
b.ring = newRing(b.endpointStates, b.config.MinRingSize, b.config.MaxRingSize, b.logger)
}
b.shouldRegenerateRing = false
var newPicker balancer.Picker
if b.endpointStates.Len() == 0 {
newPicker = base.NewErrPicker(errors.New("produced zero addresses"))
} else {
newPicker = b.newPickerLocked()
}
b.ClientConn.UpdateState(balancer.State{
ConnectivityState: state,
Picker: newPicker,
})
}
func (b *ringhashBalancer) Close() {
b.logger.Infof("Shutdown")
b.child.Close()
}
func (b *ringhashBalancer) ExitIdle() {
// ExitIdle implementation is a no-op because connections are either
// triggers from picks or from child balancer state changes.
}View on GitHub (pinned to 0c51461d27)
Solutions
- Remove the typed_per_filter_config entry for the router filter from the affected route(s) in the RouteConfiguration.
- If the control plane auto-generates per-filter-config for every filter, configure it to skip the router filter.
- Understand that gRPC routing (method matching, action selection) is handled by the resolver/config-selector, not by per-route router overrides.
Example fix
// before: RDS route with router override
route:
typed_per_filter_config:
"envoy.filters.http.router":
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
dynamic_stats: false
// after: remove the router override entirely
route:
typed_per_filter_config: {} Defensive patterns
Strategy: validation
Validate before calling
// Strip router per-route overrides before sending RDS to the data plane:
for _, vh := range routeConfig.GetVirtualHosts() {
for _, route := range vh.GetRoutes() {
cfg := route.GetTypedPerFilterConfig()
for k := range cfg {
if strings.Contains(k, "router") {
delete(cfg, k)
}
}
}
} Prevention
- Do not include the router filter in typed_per_filter_config maps; gRPC's router has no per-route config.
- Audit control-plane templates that copy Envoy configs wholesale and strip gRPC-incompatible per-route overrides.
- Document for your team that gRPC routing is handled by the config selector, not by router per-route config.
When it happens
Trigger: A RouteConfiguration route entry includes a typed_per_filter_config key for the router filter (e.g., envoy.extensions.filters.http.router.v3.Router) with a non-nil override. The xdsclient passes this override to the router builder, which does not expect one.
Common situations: An EnvoyFilter or route configuration template that was copied from a full Envoy deployment where router per-route overrides (like rewrite settings) are used, then applied to a gRPC xDS setup. A control plane that generically populates typed_per_filter_config for all listed filters. A misunderstanding that gRPC's router filter supports the same per-route config as Envoy's.
Related errors
- produced zero addresses
- no SubConn is available
- no children to pick from
- produced zero addresses
- grpc: the connection is drained
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/25ba40703aa50305.
Report an issue: GitHub.