grpc/grpc-go · error
xds_wrr_locality: missing locality weight information in…
Error message
xds_wrr_locality: missing locality weight information in endpoint %q
What it means
Thrown by wrr_locality's UpdateClientConnState when an endpoint received from the resolver does not carry the AddrInfo attribute (LocalityWeight). The xDS resolver is supposed to attach LocalityWeight to each endpoint via SetAddrInfo when processing EDS results; if it is absent the balancer cannot build weighted targets.
Solutions
- Only deploy the wrr_locality balancer behind the xDS resolver (target scheme xds:///) so endpoints arrive with LocalityWeight attached.
- If you build a custom resolver feeding this balancer, attach weights with wrrlocality.SetAddrInfo(endpoint, wrrlocality.AddrInfo{LocalityWeight: w}) for every endpoint.
- Verify the cluster is EDS-enabled in the control plane so locality weights are populated.
- Check for regressions in your gRPC version's xDS resolver EDS handling.
Example fix
// before: custom resolver emits endpoints without weight
ep := resolver.Endpoint{Addresses: addrs}
// after: attach locality weight before returning endpoints
import "google.golang.org/grpc/internal/xds/balancer/wrrlocality"
ep := wrrlocality.SetAddrInfo(resolver.Endpoint{Addresses: addrs}, wrrlocality.AddrInfo{LocalityWeight: 100}) Defensive patterns
Strategy: validation
Validate before calling
// Ensure every endpoint carries LocalityWeight before updating the balancer.
func ensureAddrInfo(eps []resolver.Endpoint) error {
for _, ep := range eps {
if _, ok := wrrlocality.AddrInfo{}.Equal; ok; _ = ok {
}
// Use the package helper: read the attribute directly.
v := ep.Attributes.Value(attributeKey{})
if _, ok := v.(wrrlocality.AddrInfo); !ok {
return fmt.Errorf("endpoint missing locality weight: %v", ep)
}
}
return nil
} Type guard
// Type guard for the AddrInfo attribute value.
func asAddrInfo(v any) (wrrlocality.AddrInfo, bool) {
ai, ok := v.(wrrlocality.AddrInfo)
return ai, ok
} Try / catch
// UpdateClientConnState returns the error; surface it from your balancer wrapper.
if err := b.UpdateClientConnState(s); err != nil {
if strings.Contains(err.Error(), "missing locality weight") {
// endpoints were not produced by the xDS resolver; switch balancer or fix resolver.
}
return err
} Prevention
- Only use xds_wrr_locality_experimental with the xDS resolver (xds:/// target).
- If feeding endpoints from a custom resolver, always call wrrlocality.SetAddrInfo.
- In tests, build endpoints with SetAddrInfo to mirror production.
When it happens
Trigger: Triggered at balancer.go:170 when getAddrInfo(ep) returns ok==false for any endpoint in s.ResolverState.Endpoints. Happens when the upstream resolver did not call SetAddrInfo (e.g. endpoints originated from a non-xDS resolver or an EDS path that skips locality weighting).
Common situations: Using the xds_wrr_locality_experimental balancer outside of an xds:/// resolved channel; a bug or partial regression in the xDS resolver that fails to set AddrInfo; mixing endpoints from a custom resolver with the xDS balancer.
Related errors
- xds_wrr_locality: config generated
- xds_wrr_locality: error marshalling prepared config
- xds_wrr_locality: invalid LBConfig
- child policy not registered
- failed to JSON marshal load balancing policy for child
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/d48f695305c7d713.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/balancer/wrrlocality/balancer.go:170
}
func (b *wrrLocalityBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
lbCfg, ok := s.BalancerConfig.(*LBConfig)
if !ok {
b.logger.Errorf("Received config with unexpected type %T: %v", s.BalancerConfig, s.BalancerConfig)
return balancer.ErrBadResolverState
}
weightedTargets := make(map[string]weightedtarget.Target)
for _, ep := range s.ResolverState.Endpoints {
// This get of LocalityID could potentially return a zero value. This
// shouldn't happen though (this attribute that is set actually gets
// used to build localities in the first place), and thus don't error
// out, and just build a weighted target with undefined behavior.
locality := xdsinternal.LocalityString(xdsinternal.LocalityIDFromEndpoint(ep))
ai, ok := getAddrInfo(ep)
if !ok {
return fmt.Errorf("xds_wrr_locality: missing locality weight information in endpoint %q", ep)
}
weightedTargets[locality] = weightedtarget.Target{Weight: ai.LocalityWeight, ChildPolicy: lbCfg.ChildPolicy}
}
wtCfg := &weightedtarget.LBConfig{Targets: weightedTargets}
wtCfgJSON, err := json.Marshal(wtCfg)
if err != nil {
// Shouldn't happen.
return fmt.Errorf("xds_wrr_locality: error marshalling prepared config: %v", wtCfg)
}
var sc serviceconfig.LoadBalancingConfig
if sc, err = b.childParser.ParseConfig(wtCfgJSON); err != nil {
return fmt.Errorf("xds_wrr_locality: config generated %v is invalid: %v", wtCfgJSON, err)
}
return b.child.UpdateClientConnState(balancer.ClientConnState{
ResolverState: s.ResolverState,
BalancerConfig: sc,
})View on GitHub (pinned to 0c51461d27)