{"record":{"id":"c3bd8678e2dd72e3","repo":"grpc/grpc-go","slug":"randomsubsetting-subsetsize-must-be-greater-than","errorCode":null,"errorMessage":"randomsubsetting: SubsetSize must be greater than 0","messagePattern":"randomsubsetting: SubsetSize must be greater than 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/randomsubsetting/randomsubsetting.go","lineNumber":94,"sourceCode":"}\n\ntype lbConfig struct {\n\tserviceconfig.LoadBalancingConfig `json:\"-\"`\n\n\tSubsetSize  uint32                         `json:\"subsetSize,omitempty\"`\n\tChildPolicy *iserviceconfig.BalancerConfig `json:\"childPolicy,omitempty\"`\n}\n\nfunc (bb) ParseConfig(s json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {\n\tlbCfg := &lbConfig{}\n\n\t// Ensure that the specified child policy is registered and validates its\n\t// config, if present.\n\tif err := json.Unmarshal(s, lbCfg); err != nil {\n\t\treturn nil, fmt.Errorf(\"randomsubsetting: json.Unmarshal failed for configuration: %s with error: %v\", string(s), err)\n\t}\n\tif lbCfg.SubsetSize == 0 {\n\t\treturn nil, fmt.Errorf(\"randomsubsetting: SubsetSize must be greater than 0\")\n\t}\n\tif lbCfg.ChildPolicy == nil {\n\t\treturn nil, fmt.Errorf(\"randomsubsetting: ChildPolicy must be specified\")\n\t}\n\n\treturn lbCfg, nil\n}\n\nfunc (bb) Name() string {\n\treturn Name\n}\n\ntype subsettingBalancer struct {\n\t*gracefulswitch.Balancer\n\n\tlogger     *internalgrpclog.PrefixLogger\n\tcfg        *lbConfig\n\thashSeed   uint64","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/randomsubsetting/randomsubsetting.go#L76-L112","documentation":"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.","triggerScenarios":"The random_subsetting_experimental service config omits subsetSize entirely (it is omitempty, so absent => 0), or explicitly sets it to 0.","commonSituations":"Copy-pasting a config template that left subsetSize out. Believing subsetSize is optional and defaults to a sensible value (it does not).","solutions":["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).","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)."],"exampleFix":"// before\nraw := `{ \"childPolicy\": { \"round_robin\": {} } }`  // subsetSize missing => 0 => error\n\n// after\nraw := `{ \"subsetSize\": 10, \"childPolicy\": { \"round_robin\": {} } }`","handlingStrategy":"validation","validationCode":"func validateSubsetSize(raw []byte) error {\n    var c struct{ SubsetSize uint32 `json:\"subsetSize\"` }\n    _ = json.Unmarshal(raw, &c)\n    if c.SubsetSize == 0 {\n        return errors.New(\"subsetSize must be > 0\")\n    }\n    return nil\n}","typeGuard":"func subsetSizePositive(c map[string]any) bool {\n    v, ok := c[\"subsetSize\"]\n    if !ok { return false }\n    f, ok := toFloat(v)\n    return ok && f > 0\n}","tryCatchPattern":null,"preventionTips":["Always set subsetSize explicitly; do not rely on a default.","Add a unit test that asserts your config builder never emits subsetSize 0.","For large fleets pick subsetSize ~ sqrt(replica_count) per gRFC A68."],"tags":["go","grpc","load-balancing","random-subsetting","config"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}