grpc/grpc-go · error
endpoints list is empty
Error message
endpoints list is empty
What it means
Returned by resolver.ValidateEndpoints (resolver/resolver.go:350) when the provided endpoints slice has length zero. Petiole (dual-stack) load-balancing policies call this on their children's results; an empty list means there is nothing to route to. The function is part of the gRPC A61 dual-stack endpoints proposal.
Source
Thrown at resolver/resolver.go:350
type AuthorityOverrider interface {
// OverrideAuthority returns the authority to use for a ClientConn with the
// given target. The implementation must generate it without blocking,
// typically in line, and must keep it unchanged.
//
// The returned string must be a valid ":authority" header value, i.e. be
// encoded according to
// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2) as
// necessary.
OverrideAuthority(Target) string
}
// ValidateEndpoints validates endpoints from a petiole policy's perspective.
// Petiole policies should call this before calling into their children. See
// [gRPC A61](https://github.com/grpc/proposal/blob/master/A61-IPv4-IPv6-dualstack-backends.md)
// for details.
func ValidateEndpoints(endpoints []Endpoint) error {
if len(endpoints) == 0 {
return errors.New("endpoints list is empty")
}
for _, endpoint := range endpoints {
for range endpoint.Addresses {
return nil
}
}
return errors.New("endpoints list contains no addresses")
}
View on GitHub (pinned to 03255a9237)
Solutions
- Investigate the resolver/registry to ensure at least one endpoint is being returned.
- Return TRANSIENT_FAILURE or keep the previous good resolver state rather than pushing an empty list.
- Add a guard in your resolver to log and skip empty updates instead of forwarding them.
- Verify the target URI and service name resolve to live backends.
Example fix
// before
cc.UpdateState(resolver.State{Addresses: nil, Endpoints: nil})
// after
if len(eps) == 0 {
logger.Warn("no endpoints; skipping update")
return
}
if err := resolver.ValidateEndpoints(eps); err != nil {
return err
}
cc.UpdateState(resolver.State{Endpoints: eps}) Defensive patterns
Strategy: validation
Validate before calling
if len(endpoints) == 0 {
return fmt.Errorf("resolver produced no endpoints")
}
if err := resolver.ValidateEndpoints(endpoints); err != nil {
return err
} Prevention
- Never push an empty endpoints list to UpdateState; keep the previous state instead.
- Log and investigate when discovery returns zero endpoints.
- Wrap ValidateEndpoints around all resolver outputs in custom balancers.
When it happens
Trigger: A custom resolver or balancer returns an empty []resolver.Endpoint slice; a DNS or xDS resolution yields no endpoints; calling ValidateEndpoints directly with a zero-length slice.
Common situations: Service discovery returns no instances (scaled to zero, misconfigured DNS); a filtering layer strips all endpoints; an upstream control plane pushing an empty resource update.
Related errors
- endpoints list contains no addresses
- rls: invalid target URI in lookup_service %s
- rls: unregistered scheme in lookup_service %s
- xds_wrr_locality: missing locality weight information in end
- dns resolver: missing address
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/8ebb502d998106e0.
Report an issue: GitHub.