grpc/grpc-go · error
pickfirst: unable to unmarshal LB policy config
Error message
pickfirst: unable to unmarshal LB policy config: %s, error: %v
What it means
Returned by pick_first's ParseConfig() (balancer/pickfirst/pickfirst.go:99) when json.Unmarshal of the raw config into pfConfig fails. pfConfig has a single optional boolean field 'shuffleAddressList'. The %s shows the raw JSON and %v the unmarshal error. This is the new pick-first leaf balancer (the universal leaf policy). The error fails service config parsing.
Solutions
- Run the service config JSON through a JSON validator.
- Ensure shuffleAddressList is a boolean if present.
- Read the %s (raw JSON) and %v (error) to find the exact offending token.
- If the config is valid JSON but has unknown fields, note that json.Unmarshal ignores unknown fields unless it is a type mismatch.
Example fix
// before: shuffleAddressList as a string
grpc.WithDefaultServiceConfig(`{"loadBalancingConfig":[{"pick_first":{"shuffleAddressList":"true"}}]}`)
// after: shuffleAddressList as a boolean
grpc.WithDefaultServiceConfig(`{"loadBalancingConfig":[{"pick_first":{"shuffleAddressList":true}}]}`) Defensive patterns
Strategy: validation
Validate before calling
// Validate pick_first config JSON before applying.
func validatePickFirstConfig(js string) error {
var cfg struct {
ShuffleAddressList bool `json:"shuffleAddressList"`
}
return json.Unmarshal([]byte(js), &cfg)
} Prevention
- Ensure shuffleAddressList is a JSON boolean, not a string.
- Validate service config JSON in CI.
- Test config parsing with sample inputs.
When it happens
Trigger: The pick_first policy config entry in the service config / xDS resource is invalid JSON, or contains a field of the wrong type (e.g. shuffleAddressList as a string). ParseConfig() is called by the channel during service config parsing.
Common situations: Malformed service config JSON string; shuffleAddressList given as "true" (string) instead of true (boolean); an xDS control plane sends a malformed pick_first config; trailing comma or unquoted key in a hand-written config.
Related errors
- least-request: unable to unmarshal LBConfig
- randomsubsetting: json.Unmarshal failed for configuration
- expected a JSON struct with one entry; received entry
- invalid requestHashHeader
- invalid requestHashHeader
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/48db52b356cd6e52.
Report an issue: GitHub.
Appendix: source
Thrown at balancer/pickfirst/pickfirst.go:99
b := &pickfirstBalancer{
cc: cc,
subConns: resolver.NewAddressMapV2[*scData](),
state: connectivity.Connecting,
cancelConnectionTimer: func() {},
}
b.logger = internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf(logPrefix, b))
return b
}
func (b pickfirstBuilder) Name() string {
return Name
}
func (pickfirstBuilder) ParseConfig(js json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
var cfg pfConfig
if err := json.Unmarshal(js, &cfg); err != nil {
return nil, fmt.Errorf("pickfirst: unable to unmarshal LB policy config: %s, error: %v", string(js), err)
}
return cfg, nil
}
// EnableHealthListener updates the state to configure pickfirst for using a
// generic health listener.
//
// # Experimental
//
// Notice: This API is EXPERIMENTAL and may be changed or removed in a later
// release.
func EnableHealthListener(state resolver.State) resolver.State {
state.Attributes = state.Attributes.WithValue(enableHealthListenerKeyType{}, true)
return state
}
type pfConfig struct {
serviceconfig.LoadBalancingConfig `json:"-"`View on GitHub (pinned to 0c51461d27)