grpc/grpc-go · error
invalid requestHashHeader %q: %v
Error message
invalid requestHashHeader %q: %v
What it means
Returned by ringhash.parseConfig (config.go:69-71) when requestHashHeader (after ToLower) fails metadata.ValidateKey. Per gRFC A76, the request hash header must be a valid gRPC metadata key: lowercase alphanumeric plus '-' and '_', starting with a letter, 1-63 chars in the name part. The %q is the lowercased header and %v is the ValidateKey error.
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 03255a9237)
Solutions
- Set requestHashHeader to a valid metadata key: lowercase, alphanumeric with '-'/'_', e.g. "user-id".
- Confirm the header you send in metadata exactly matches (case-insensitively) the configured key.
- If you do not need explicit hash keys, leave requestHashHeader unset so ringhash falls back to the xDS-provided hash.
Example fix
// before
raw := `{"requestHashHeader": "X-User-Id"}` // uppercase/invalid -> error
// after
raw := `{"requestHashHeader": "user-id"}` Defensive patterns
Strategy: validation
Validate before calling
import "google.golang.org/grpc/internal/metadata"
func validateRequestHashHeader(h string) error {
h = strings.ToLower(h)
return metadata.ValidateKey(h)
} Type guard
func isValidMetadataKey(h string) bool {
h = strings.ToLower(h)
if h == "" || len(h) > 63 { return false }
for _, r := range h {
if !(r >= 'a' && r <= 'z') && !(r >= '0' && r <= '9') && r != '-' && r != '_' && r != '.' {
return false
}
}
return true
} Prevention
- Use lowercase, simple header names for hash keys.
- Match the key you actually attach to outgoing metadata.
- Leave requestHashHeader unset if you don't need explicit hashing.
When it happens
Trigger: ring_hash config sets requestHashHeader to a string with uppercase letters (pre-lowercase), illegal characters (spaces, colons, dots), empty, or otherwise not matching the metadata key grammar.
Common situations: Using an HTTP header name verbatim (e.g. "X-User-Id", "User Id") instead of a valid gRPC metadata key. Only enabled when envconfig.RingHashSetRequestHashKey is true (xDS-driven), so commonly seen in xDS deployments.
Related errors
- invalid requestHashHeader %q, key must not end with "-bin"
- min_ring_size value of %d is greater than max supported valu
- max_ring_size value of %d is greater than max supported valu
- min %v is greater than max %v
- randomsubsetting: json.Unmarshal failed for configuration: %
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/4e3dadf8573a2e7c.
Report an issue: GitHub.