grpc/grpc-go · error

xds_wrr_locality: invalid LBConfig: child policy field must

Error message

xds_wrr_locality: invalid LBConfig: child policy field must be set

What it means

Returned by the xds_wrr_locality balancer's ParseConfig (wrrlocality/balancer.go:97-98) when the JSON LB config unmarshals to nil or its ChildPolicy field is nil. The weighted-round-robin-per-locality balancer delegates to the weighted_target child, so a missing child_policy makes the config unusable and is rejected at parse time.

Source

Thrown at internal/xds/balancer/wrrlocality/balancer.go:98

		return nil
	}
	wrrL := &wrrLocalityBalancer{
		child:       wtb,
		childParser: wtbCfgParser,
	}

	wrrL.logger = prefixLogger(wrrL)
	wrrL.logger.Infof("Created")
	return wrrL
}

func (bb) ParseConfig(s json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
	var lbCfg *LBConfig
	if err := json.Unmarshal(s, &lbCfg); err != nil {
		return nil, fmt.Errorf("xds_wrr_locality: invalid LBConfig: %s, error: %v", string(s), err)
	}
	if lbCfg == nil || lbCfg.ChildPolicy == nil {
		return nil, errors.New("xds_wrr_locality: invalid LBConfig: child policy field must be set")
	}
	return lbCfg, nil
}

type attributeKey struct{}

// Equal allows the values to be compared by Attributes.Equal.
func (a AddrInfo) Equal(o any) bool {
	oa, ok := o.(AddrInfo)
	return ok && oa.LocalityWeight == a.LocalityWeight
}

// AddrInfo is the locality weight of the locality an address is a part of.
type AddrInfo struct {
	LocalityWeight uint32
}

// SetAddrInfo returns a copy of endpoint in which the Attributes field is

View on GitHub (pinned to 03255a9237)

Solutions

  1. Add a non-null childPolicy to the xds_wrr_locality config, typically weighted_target or round_robin.
  2. If generating config programmatically, assert childPolicy != nil before serializing.
  3. Validate the JSON against the expected schema (childPolicy is required) before applying via WithServiceConfig.

Example fix

// before
//   { "xds_wrr_locality": {} }
// after
//   { "xds_wrr_locality": { "childPolicy": [ { "weighted_target": { "targets": {} } } ] } }
Defensive patterns

Strategy: validation

Validate before calling

// Validate the wrr_locality config has a child policy before applying.
func validateWrrLocality(raw json.RawMessage) error {
    var c struct {
        ChildPolicy json.RawMessage `json:"childPolicy"`
    }
    if err := json.Unmarshal(raw, &c); err != nil { return err }
    if len(c.ChildPolicy) == 0 || string(c.ChildPolicy) == "null" {
        return errors.New("xds_wrr_locality requires a non-null childPolicy")
    }
    return nil
}

Prevention

When it happens

Trigger: Providing an xds_wrr_locality service/LB config JSON whose 'childPolicy' (child_policy) field is absent or null, e.g. {"xds_wrr_locality":{}}. The json.Unmarshal succeeds but lbCfg or lbCfg.ChildPolicy is nil.

Common situations: Hand-authoring a service config and forgetting childPolicy; a control plane translating xDS endpoint config that drops the child policy; version mismatch where an older field name is used.

Related errors


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