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

  1. Investigate the resolver/registry to ensure at least one endpoint is being returned.
  2. Return TRANSIENT_FAILURE or keep the previous good resolver state rather than pushing an empty list.
  3. Add a guard in your resolver to log and skip empty updates instead of forwarding them.
  4. 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

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


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