{"record":{"id":"4e3dadf8573a2e7c","repo":"grpc/grpc-go","slug":"invalid-requesthashheader-q-v","errorCode":null,"errorMessage":"invalid requestHashHeader %q: %v","messagePattern":"invalid requestHashHeader %q: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/ringhash/config.go","lineNumber":70,"sourceCode":"\t\tcfg.MaxRingSize = defaultMaxSize\n\t}\n\tif cfg.MinRingSize > cfg.MaxRingSize {\n\t\treturn nil, fmt.Errorf(\"min %v is greater than max %v\", cfg.MinRingSize, cfg.MaxRingSize)\n\t}\n\tif cfg.MinRingSize > envconfig.RingHashCap {\n\t\tcfg.MinRingSize = envconfig.RingHashCap\n\t}\n\tif cfg.MaxRingSize > envconfig.RingHashCap {\n\t\tcfg.MaxRingSize = envconfig.RingHashCap\n\t}\n\tif !envconfig.RingHashSetRequestHashKey {\n\t\tcfg.RequestHashHeader = \"\"\n\t}\n\tif cfg.RequestHashHeader != \"\" {\n\t\tcfg.RequestHashHeader = strings.ToLower(cfg.RequestHashHeader)\n\t\t// See rules in https://github.com/grpc/proposal/blob/master/A76-ring-hash-improvements.md#explicitly-setting-the-request-hash-key\n\t\tif err := metadata.ValidateKey(cfg.RequestHashHeader); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid requestHashHeader %q: %v\", cfg.RequestHashHeader, err)\n\t\t}\n\t\tif strings.HasSuffix(cfg.RequestHashHeader, \"-bin\") {\n\t\t\treturn nil, fmt.Errorf(\"invalid requestHashHeader %q: key must not end with \\\"-bin\\\"\", cfg.RequestHashHeader)\n\t\t}\n\t}\n\treturn &cfg, nil\n}\n","sourceCodeStart":52,"sourceCodeEnd":78,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/balancer/ringhash/config.go#L52-L78","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: invalid header name (uppercase / invalid chars)\ngrpc.WithDefaultServiceConfig(`{\"loadBalancingConfig\":[{\"ring_hash_experimental\":{\"requestHashHeader\":\"User-Id\"}}]}`)\n\n// after: valid lowercase header name (the code lowercases it, but keep it clean)\ngrpc.WithDefaultServiceConfig(`{\"loadBalancingConfig\":[{\"ring_hash_experimental\":{\"requestHashHeader\":\"user-id\"}}]}`)","handlingStrategy":"validation","validationCode":"// Validate the header name using the same rules as gRPC metadata.\nfunc validateRequestHashHeader(h string) error {\n    h = strings.ToLower(h)\n    if err := metadata.ValidateKey(h); err != nil {\n        return fmt.Errorf(\"invalid requestHashHeader %q: %w\", h, err)\n    }\n    if strings.HasSuffix(h, \"-bin\") {\n        return fmt.Errorf(\"requestHashHeader must not end with -bin\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use only lowercase alphanumeric plus '-'/'_' for requestHashHeader, starting with a letter.","Validate header names in config generation before pushing to clients."],"tags":["grpc","balancer","ringhash","config","validation","metadata","header"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}