grpc/grpc-go · error
invalid requestHashHeader
Error message
invalid requestHashHeader %q: key must not end with "-bin"
What it means
Returned by ringhash's parseConfig() (balancer/ringhash/config.go:73) when requestHashHeader ends with the suffix '-bin'. Binary headers (-bin suffix) carry raw bytes and cannot be used as a request-hash key because the hash expects a string value. This is enforced after ValidateKey passes.
Solutions
- Use a non-binary (ASCII string) metadata header as requestHashHeader — it must not end with '-bin'.
- If you need to hash on a binary header, convert it to a base64 ASCII header first.
Example fix
// before: binary header used as hash key — rejected
grpc.WithDefaultServiceConfig(`{"loadBalancingConfig":[{"ring_hash_experimental":{"requestHashHeader":"trace-bin"}}]}`)
// after: use a non-binary ASCII header
grpc.WithDefaultServiceConfig(`{"loadBalancingConfig":[{"ring_hash_experimental":{"requestHashHeader":"trace-id"}}]}`) Defensive patterns
Strategy: validation
Validate before calling
func rejectBinaryHeader(h string) error {
if strings.HasSuffix(strings.ToLower(h), "-bin") {
return errors.New("requestHashHeader must not end with -bin")
}
return nil
} Prevention
- Never use a '-bin' (binary) metadata header as the ring hash key.
- Use a base64-encoded ASCII header if you need to hash binary data.
When it happens
Trigger: requestHashHeader is a syntactically valid key but ends in '-bin' (e.g. 'my-key-bin'). The check at line 72 (strings.HasSuffix) fires.
Common situations: Operator picks a binary metadata header as the hash source by mistake; an xDS control plane reuses an existing '-bin' header name.
Related errors
- invalid requestHashHeader
- max_ring_size value of
- min_ring_size value of
- min is greater than max
- least-request: lbConfig.choiceCount
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/1e613d1bdce79ddf.
Report an issue: GitHub.
Appendix: source
Thrown at balancer/ringhash/config.go:73
return nil, fmt.Errorf("min %v is greater than max %v", cfg.MinRingSize, cfg.MaxRingSize)
}
if cfg.MinRingSize > envconfig.RingHashCap {
cfg.MinRingSize = envconfig.RingHashCap
}
if cfg.MaxRingSize > envconfig.RingHashCap {
cfg.MaxRingSize = envconfig.RingHashCap
}
if !envconfig.RingHashSetRequestHashKey {
cfg.RequestHashHeader = ""
}
if cfg.RequestHashHeader != "" {
cfg.RequestHashHeader = strings.ToLower(cfg.RequestHashHeader)
// See rules in https://github.com/grpc/proposal/blob/master/A76-ring-hash-improvements.md#explicitly-setting-the-request-hash-key
if err := metadata.ValidateKey(cfg.RequestHashHeader); err != nil {
return nil, fmt.Errorf("invalid requestHashHeader %q: %v", cfg.RequestHashHeader, err)
}
if strings.HasSuffix(cfg.RequestHashHeader, "-bin") {
return nil, fmt.Errorf("invalid requestHashHeader %q: key must not end with \"-bin\"", cfg.RequestHashHeader)
}
}
return &cfg, nil
}
View on GitHub (pinned to 0c51461d27)