grpc/grpc-go · error
invalid requestHashHeader
Error message
invalid requestHashHeader %q: %v
What it means
Returned by ringhash's parseConfig() (balancer/ringhash/config.go:70) when the requestHashHeader (lowercased at line 67) fails metadata.ValidateKey(). Per gRFC A76, requestHashHeader names the gRPC metadata key whose value is hashed to pick a consistent ring entry. ValidateKey enforces the gRPC header naming rules (lowercase alphanumeric plus '-' and '_', must start with a letter).
Solutions
- Use a valid gRPC metadata key: lowercase letters, digits, '-' and '_', starting with a letter.
- Avoid uppercase, spaces, colons, and other punctuation in requestHashHeader.
- Ensure envconfig.RingHashSetRequestHashKey is intentionally enabled if you are setting this field.
Example fix
// before: invalid header name (uppercase / invalid chars)
grpc.WithDefaultServiceConfig(`{"loadBalancingConfig":[{"ring_hash_experimental":{"requestHashHeader":"User-Id"}}]}`)
// after: valid lowercase header name (the code lowercases it, but keep it clean)
grpc.WithDefaultServiceConfig(`{"loadBalancingConfig":[{"ring_hash_experimental":{"requestHashHeader":"user-id"}}]}`) Defensive patterns
Strategy: validation
Validate before calling
// Validate the header name using the same rules as gRPC metadata.
func validateRequestHashHeader(h string) error {
h = strings.ToLower(h)
if err := metadata.ValidateKey(h); err != nil {
return fmt.Errorf("invalid requestHashHeader %q: %w", h, err)
}
if strings.HasSuffix(h, "-bin") {
return fmt.Errorf("requestHashHeader must not end with -bin")
}
return nil
} Prevention
- Use only lowercase alphanumeric plus '-'/'_' for requestHashHeader, starting with a letter.
- Validate header names in config generation before pushing to clients.
When it happens
Trigger: The ring_hash_experimental config sets requestHashHeader to an invalid header name (uppercase letters, spaces, special characters, or empty after trimming). After lowercasing, metadata.ValidateKey returns an error at line 69. Note: this only applies when envconfig.RingHashSetRequestHashKey is true (line 63), otherwise the header is cleared.
Common situations: requestHashHeader set to a value like 'User-Id' (the code lowercases it, but other invalid chars remain); a header with spaces or dots; an xDS control plane sends an invalid 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/4e3dadf8573a2e7c.
Report an issue: GitHub.
Appendix: source
Thrown at balancer/ringhash/config.go:70
cfg.MaxRingSize = defaultMaxSize
}
if cfg.MinRingSize > cfg.MaxRingSize {
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)