grpc/grpc-go · error

randomsubsetting: SubsetSize must be greater than 0

Error message

randomsubsetting: SubsetSize must be greater than 0

What it means

Returned by randomsubsetting.ParseConfig (randomsubsetting.go:93-95) when SubsetSize is 0 after unmarshalling. SubsetSize controls how many endpoints the policy keeps in its random subset (per A68), and zero would produce an empty subset, so the policy rejects it. The field is required and must be a positive uint32.

Source

Thrown at balancer/randomsubsetting/randomsubsetting.go:94

}

type lbConfig struct {
	serviceconfig.LoadBalancingConfig `json:"-"`

	SubsetSize  uint32                         `json:"subsetSize,omitempty"`
	ChildPolicy *iserviceconfig.BalancerConfig `json:"childPolicy,omitempty"`
}

func (bb) ParseConfig(s json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
	lbCfg := &lbConfig{}

	// Ensure that the specified child policy is registered and validates its
	// config, if present.
	if err := json.Unmarshal(s, lbCfg); err != nil {
		return nil, fmt.Errorf("randomsubsetting: json.Unmarshal failed for configuration: %s with error: %v", string(s), err)
	}
	if lbCfg.SubsetSize == 0 {
		return nil, fmt.Errorf("randomsubsetting: SubsetSize must be greater than 0")
	}
	if lbCfg.ChildPolicy == nil {
		return nil, fmt.Errorf("randomsubsetting: ChildPolicy must be specified")
	}

	return lbCfg, nil
}

func (bb) Name() string {
	return Name
}

type subsettingBalancer struct {
	*gracefulswitch.Balancer

	logger     *internalgrpclog.PrefixLogger
	cfg        *lbConfig
	hashSeed   uint64

View on GitHub (pinned to 03255a9237)

Solutions

  1. Add a positive subsetSize to the config, e.g. a value matching your fan-out target (commonly equal to or less than the number of backend replicas).
  2. Pick subsetSize based on the desired subset fan-out per gRFC A68 (e.g. a small constant like the square root of endpoint count for large fleets).

Example fix

// before
raw := `{ "childPolicy": { "round_robin": {} } }`  // subsetSize missing => 0 => error

// after
raw := `{ "subsetSize": 10, "childPolicy": { "round_robin": {} } }`
Defensive patterns

Strategy: validation

Validate before calling

func validateSubsetSize(raw []byte) error {
    var c struct{ SubsetSize uint32 `json:"subsetSize"` }
    _ = json.Unmarshal(raw, &c)
    if c.SubsetSize == 0 {
        return errors.New("subsetSize must be > 0")
    }
    return nil
}

Type guard

func subsetSizePositive(c map[string]any) bool {
    v, ok := c["subsetSize"]
    if !ok { return false }
    f, ok := toFloat(v)
    return ok && f > 0
}

Prevention

When it happens

Trigger: The random_subsetting_experimental service config omits subsetSize entirely (it is omitempty, so absent => 0), or explicitly sets it to 0.

Common situations: Copy-pasting a config template that left subsetSize out. Believing subsetSize is optional and defaults to a sensible value (it does not).

Related errors


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