grpc/grpc-go · warning

endpoints list is empty

Error message

endpoints list is empty

What it means

Returned by resolver.ValidateEndpoints when the endpoints slice passed in has length 0. Petiole (dual-stack endpoints, gRFC A61) policies call this to enforce that at least one endpoint exists before delegating to child policies; an empty list means there is nothing to dial.

Solutions

  1. At the resolver/producer side, skip emitting a resolved address update when endpoints is empty, or send an empty-state error instead of a zero-length list.
  2. Check the upstream EDS/DNS source: confirm endpoints actually exist and are not filtered out by a health/ locality filter.

Example fix

// before
func buildAddrs(eps []resolver.Endpoint) []resolver.Address {
    _ = resolver.ValidateEndpoints(eps) // errors when eps is empty
    ...
}
// after
func buildAddrs(eps []resolver.Endpoint) ([]resolver.Address, error) {
    if err := resolver.ValidateEndpoints(eps); err != nil { return nil, err }
    ...
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate before producing a resolver update.
if len(eps) == 0 {
    // Optionally surface an error state instead of an empty update.
    return fmt.Errorf("no endpoints available for %s", target)
}

Type guard

func hasEndpoints(eps []resolver.Endpoint) bool { return len(eps) > 0 }

Try / catch

if err := resolver.ValidateEndpoints(eps); err != nil { if strings.Contains(err.Error(), "empty") { // back off / keep previous addresses rather than flushing the picker return } return err }

Prevention

When it happens

Trigger: A resolver or balancer passes an empty []Endpoint slice to ValidateEndpoints. Occurs when an xDS/EDS update removes all endpoints, or when a custom resolver produces an empty list (e.g. DNS returned no records and the resolver propagated that).

Common situations: Endpoint discovery returned zero hosts (scaled to zero, all endpoints evicted). Resolver bug drops endpoints before calling ValidateEndpoints. Transient control-plane state where the cluster has no healthy localities.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/8ebb502d998106e0. Report an issue: GitHub.

Appendix: 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 0c51461d27)