{"record":{"id":"3a86c597811714b4","repo":"grpc/grpc-go","slug":"least-request-lbconfig-choicecount-v-must-be","errorCode":null,"errorMessage":"least-request: lbConfig.choiceCount: %v, must be >= 2","messagePattern":"least-request: lbConfig\\.choiceCount: (.+?), must be >= 2","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/leastrequest/leastrequest.go","lineNumber":73,"sourceCode":"\n\t// ChoiceCount is the number of random SubConns to sample to find the one\n\t// with the fewest outstanding requests. If unset, defaults to 2. If set to\n\t// < 2, the config will be rejected, and if set to > 10, will become 10.\n\tChoiceCount uint32 `json:\"choiceCount,omitempty\"`\n}\n\ntype bb struct{}\n\nfunc (bb) ParseConfig(s json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {\n\tlbConfig := &LBConfig{\n\t\tChoiceCount: 2,\n\t}\n\tif err := json.Unmarshal(s, lbConfig); err != nil {\n\t\treturn nil, fmt.Errorf(\"least-request: unable to unmarshal LBConfig: %v\", err)\n\t}\n\t// \"If `choice_count < 2`, the config will be rejected.\" - A48\n\tif lbConfig.ChoiceCount < 2 { // sweet\n\t\treturn nil, fmt.Errorf(\"least-request: lbConfig.choiceCount: %v, must be >= 2\", lbConfig.ChoiceCount)\n\t}\n\t// \"If a LeastRequestLoadBalancingConfig with a choice_count > 10 is\n\t// received, the least_request_experimental policy will set choice_count =\n\t// 10.\" - A48\n\tif lbConfig.ChoiceCount > 10 {\n\t\tlbConfig.ChoiceCount = 10\n\t}\n\treturn lbConfig, nil\n}\n\nfunc (bb) Name() string {\n\treturn Name\n}\n\nfunc (bb) Build(cc balancer.ClientConn, bOpts balancer.BuildOptions) balancer.Balancer {\n\tb := &leastRequestBalancer{\n\t\tClientConn:        cc,\n\t\tendpointRPCCounts: resolver.NewEndpointMap[*atomic.Int32](),","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/leastrequest/leastrequest.go#L55-L91","documentation":"Raised by least-request ParseConfig after a successful unmarshal if choiceCount < 2. Per gRPC A48, the least-request policy samples between choiceCount SubConns; a value below 2 makes the algorithm meaningless (no choice to make) and is explicitly rejected. Note values > 10 are not rejected but silently clamped to 10.","triggerScenarios":"The service config sets choiceCount to 0 or 1 (or omits it in a way that yields < 2 after explicit assignment). The `lbConfig.ChoiceCount < 2` check fires after unmarshal. (Default is 2, so you must have explicitly set it below 2.)","commonSituations":"Setting choiceCount to 1 thinking it disables sampling; a config generator defaulting to 0; misreading the schema and setting the old default; copying a value from another balancer's config.","solutions":["Set choiceCount to a value between 2 and 10 (inclusive).","If you want the default behaviour, omit choiceCount entirely (it defaults to 2).","Remember values > 10 are clamped to 10, so 2-10 is the effective range.","Lint the service config for choiceCount in [2,10] before deploy."],"exampleFix":"// before:\n{ \"loadBalancingConfig\": { \"least_request_experimental\": { \"choiceCount\": 1 } } }   // rejected\n\n// after:\n{ \"loadBalancingConfig\": { \"least_request_experimental\": { \"choiceCount\": 2 } } }   // or omit entirely","handlingStrategy":"validation","validationCode":"func validateChoiceCount(raw json.RawMessage) error {\n    var c struct {\n        ChoiceCount uint32 `json:\"choiceCount,omitempty\"`\n    }\n    if err := json.Unmarshal(raw, &c); err != nil { return err }\n    // default is 2 when omitted; if explicitly set, must be 2..10\n    var presence struct{ ChoiceCount *uint32 `json:\"choiceCount\"` }\n    json.Unmarshal(raw, &presence)\n    if presence.ChoiceCount != nil && (*presence.ChoiceCount < 2 || *presence.ChoiceCount > 10) {\n        return fmt.Errorf(\"choiceCount %d out of range [2,10]\", *presence.ChoiceCount)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep choiceCount in [2,10] (values >10 are silently clamped).","Omit choiceCount to accept the default of 2.","Lint service config for choiceCount bounds in CI.","Document the A48 clamping behaviour for config authors."],"tags":["balancer","least-request","service-config","config","validation"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}