grpc/grpc-go · error
least-request: unable to unmarshal LBConfig: %v
Error message
least-request: unable to unmarshal LBConfig: %v
What it means
Raised by the least-request balancer's ParseConfig when the JSON service config for the least_request_experimental policy cannot be unmarshalled into LBConfig. The wrapped %v is the encoding/json error. Because ParseConfig is invoked by the channel when applying service config, this error causes the config to be rejected (the channel falls back to the default policy).
Source
Thrown at balancer/leastrequest/leastrequest.go:69
// LBConfig is the balancer config for least_request_experimental balancer.
type LBConfig struct {
serviceconfig.LoadBalancingConfig `json:"-"`
// ChoiceCount is the number of random SubConns to sample to find the one
// with the fewest outstanding requests. If unset, defaults to 2. If set to
// < 2, the config will be rejected, and if set to > 10, will become 10.
ChoiceCount uint32 `json:"choiceCount,omitempty"`
}
type bb struct{}
func (bb) ParseConfig(s json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
lbConfig := &LBConfig{
ChoiceCount: 2,
}
if err := json.Unmarshal(s, lbConfig); err != nil {
return nil, fmt.Errorf("least-request: unable to unmarshal LBConfig: %v", err)
}
// "If `choice_count < 2`, the config will be rejected." - A48
if lbConfig.ChoiceCount < 2 { // sweet
return nil, fmt.Errorf("least-request: lbConfig.choiceCount: %v, must be >= 2", lbConfig.ChoiceCount)
}
// "If a LeastRequestLoadBalancingConfig with a choice_count > 10 is
// received, the least_request_experimental policy will set choice_count =
// 10." - A48
if lbConfig.ChoiceCount > 10 {
lbConfig.ChoiceCount = 10
}
return lbConfig, nil
}
func (bb) Name() string {
return Name
}
View on GitHub (pinned to 03255a9237)
Solutions
- Validate the least_request_experimental block is valid JSON (run through `jq`).
- Ensure choiceCount is a JSON number (uint32), not a string.
- Remove any unrecognized fields or upgrade grpc-go so the struct accepts them.
- Test the service config JSON by calling ParseConfig directly in a unit test.
Example fix
// before (choiceCount as string -> unmarshal error):
{ "loadBalancingConfig": { "least_request_experimental": { "choiceCount": "2" } } }
// after:
{ "loadBalancingConfig": { "least_request_experimental": { "choiceCount": 2 } } } Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: unmarshal the least_request_experimental config exactly as
// the balancer does, to surface type errors before the channel applies it.
type lrConfig struct {
ChoiceCount uint32 `json:"choiceCount,omitempty"`
}
func validateLeastRequestConfig(raw json.RawMessage) error {
var c lrConfig
if err := json.Unmarshal(raw, &c); err != nil {
return fmt.Errorf("least-request: unable to unmarshal LBConfig: %v", err)
}
if c.ChoiceCount < 2 {
return fmt.Errorf("least-request: choiceCount %v must be >= 2", c.ChoiceCount)
}
return nil
} Prevention
- Validate service config JSON with `jq` and the gRPC schema.
- Ensure numeric fields are JSON numbers, not strings.
- Unit-test ParseConfig directly with your config payload.
- Remove unknown fields or upgrade grpc-go.
When it happens
Trigger: The service config contains a least_request_experimental block whose JSON is malformed or whose fields have wrong types (e.g. choiceCount as a string instead of a number). json.Unmarshal fails inside ParseConfig.
Common situations: Typo in the service config JSON; sending choiceCount as "2" (string) instead of 2; a stray field that breaks the struct decode; an older client receiving a config field from a newer schema that the LBConfig struct rejects on type.
Related errors
- least-request: lbConfig.choiceCount: %v, must be >= 2
- pickfirst: unable to unmarshal LB policy config: %s, error:
- xds: unable to unmarshal lbconfig: %s, error: %v
- xds: unable to unmarshal LBconfig: %s, error: %v
- bad resolver state
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/a5929bce946a67fc.
Report an issue: GitHub.