{"record":{"id":"c4788f4aca43f45b","repo":"grpc/grpc-go","slug":"rls-grpckeybuilder-in-routelookupconfig-has-requi","errorCode":null,"errorMessage":"rls: GrpcKeyBuilder in RouteLookupConfig has required_match field set {%+v}","messagePattern":"rls: GrpcKeyBuilder in RouteLookupConfig has required_match field set (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/rls/internal/keys/builder.go","lineNumber":56,"sourceCode":"\tkbs := cfg.GetGrpcKeybuilders()\n\tif len(kbs) == 0 {\n\t\treturn nil, errors.New(\"rls: RouteLookupConfig does not contain any GrpcKeyBuilder\")\n\t}\n\n\tbm := make(map[string]builder)\n\tfor _, kb := range kbs {\n\t\t// Extract keys from `headers`, `constant_keys` and `extra_keys` fields\n\t\t// and populate appropriate values in the builder struct. Also ensure\n\t\t// that keys are not repeated.\n\t\tvar matchers []matcher\n\t\tseenKeys := make(map[string]bool)\n\t\tconstantKeys := kb.GetConstantKeys()\n\t\tfor k := range kb.GetConstantKeys() {\n\t\t\tseenKeys[k] = true\n\t\t}\n\t\tfor _, h := range kb.GetHeaders() {\n\t\t\tif h.GetRequiredMatch() {\n\t\t\t\treturn nil, fmt.Errorf(\"rls: GrpcKeyBuilder in RouteLookupConfig has required_match field set {%+v}\", kbs)\n\t\t\t}\n\t\t\tkey := h.GetKey()\n\t\t\tif seenKeys[key] {\n\t\t\t\treturn nil, fmt.Errorf(\"rls: GrpcKeyBuilder in RouteLookupConfig contains repeated key %q across headers, constant_keys and extra_keys {%+v}\", key, kbs)\n\t\t\t}\n\t\t\tseenKeys[key] = true\n\t\t\tmatchers = append(matchers, matcher{key: h.GetKey(), names: h.GetNames()})\n\t\t}\n\t\tif seenKeys[kb.GetExtraKeys().GetHost()] {\n\t\t\treturn nil, fmt.Errorf(\"rls: GrpcKeyBuilder in RouteLookupConfig contains repeated key %q in extra_keys from constant_keys or headers {%+v}\", kb.GetExtraKeys().GetHost(), kbs)\n\t\t}\n\t\tif seenKeys[kb.GetExtraKeys().GetService()] {\n\t\t\treturn nil, fmt.Errorf(\"rls: GrpcKeyBuilder in RouteLookupConfig contains repeated key %q in extra_keys from constant_keys or headers {%+v}\", kb.GetExtraKeys().GetService(), kbs)\n\t\t}\n\t\tif seenKeys[kb.GetExtraKeys().GetMethod()] {\n\t\t\treturn nil, fmt.Errorf(\"rls: GrpcKeyBuilder in RouteLookupConfig contains repeated key %q in extra_keys from constant_keys or headers {%+v}\", kb.GetExtraKeys().GetMethod(), kbs)\n\t\t}\n\t\tb := builder{","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/rls/internal/keys/builder.go#L38-L74","documentation":"Each header entry in a GrpcKeyBuilder has a required_match flag. The RLS key-builder semantics do not support conditional (required) header matching — all configured header keys are extracted unconditionally — so MakeBuilderMap rejects any header with required_match==true.","triggerScenarios":"A grpc_keybuilders[].headers[] entry with \"required_match\": true (proto HeaderMatcher.required_match). E.g. {\"key\":\"region\",\"names\":[\"x-region\"],\"required_match\":true}.","commonSituations":"Reusing HeaderMatcher structs from gRPC service config (where required_match is valid) inside an RLS key builder; translating routing rules verbatim into RLS key builders.","solutions":["Remove required_match (or set it false) from every header in every GrpcKeyBuilder.","If you need presence-based routing, handle it upstream of RLS or use distinct key builders per path.","Audit all grpc_keybuilders[].headers entries for the field."],"exampleFix":"// before\n\"headers\": [{ \"key\": \"region\", \"names\": [\"x-region\"], \"required_match\": true }]\n// after\n\"headers\": [{ \"key\": \"region\", \"names\": [\"x-region\"] }]","handlingStrategy":"validation","validationCode":"func validateNoRequiredMatch(cfg *rlspb.RouteLookupConfig) error {\n    for bi, kb := range cfg.GetGrpcKeybuilders() {\n        for hi, h := range kb.GetHeaders() {\n            if h.GetRequiredMatch() {\n                return fmt.Errorf(\"keybuilder[%d].header[%d] has required_match set\", bi, hi)\n            }\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not reuse gRPC routing HeaderMatcher structs verbatim in RLS key builders.","Audit every header entry for required_match before deploying.","Strip required_match when converting routing rules to key builders."],"tags":["rls","service-config","config-validation","go","grpc","key-builder"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}