{"record":{"id":"a08c3046c5ce30c0","repo":"grpc/grpc-go","slug":"rls-grpckeybuilder-in-routelookupconfig-contains-a08c30","errorCode":null,"errorMessage":"rls: GrpcKeyBuilder in RouteLookupConfig contains repeated key %q in extra_keys from constant_keys or headers {%+v}","messagePattern":"rls: GrpcKeyBuilder in RouteLookupConfig contains repeated key %q in extra_keys from constant_keys or headers (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/rls/internal/keys/builder.go","lineNumber":66,"sourceCode":"\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{\n\t\t\theaderKeys:   matchers,\n\t\t\tconstantKeys: constantKeys,\n\t\t\thostKey:      kb.GetExtraKeys().GetHost(),\n\t\t\tserviceKey:   kb.GetExtraKeys().GetService(),\n\t\t\tmethodKey:    kb.GetExtraKeys().GetMethod(),\n\t\t}\n\n\t\t// Store the builder created above in the BuilderMap based on the value\n\t\t// of the `Names` field, which wraps incoming request's service and\n\t\t// method. Also, ensure that there are no repeated `Names` field.","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/rls/internal/keys/builder.go#L48-L84","documentation":"extra_keys is a separate struct with host/service/method fields that name which RLS key the request's host should populate. After headers and constant_keys are seeded into seenKeys, MakeBuilderMap checks each extra_keys field for collision. This specific error is for the host field: extra_keys.host must not equal a key already used in constant_keys or headers.","triggerScenarios":"A GrpcKeyBuilder whose extra_keys.host equals a constant_keys key or a header key. E.g. constant_keys/headers use \"host\" and extra_keys.host is also \"host\".","commonSituations":"Naming the host-derived key \"host\" while a constant or header also uses \"host\"; copy-pasting extra_keys without checking overlap with headers.","solutions":["Rename either the extra_keys.host value or the colliding constant/header key so they differ.","Drop the redundant constant/header entry if the host key already conveys that value.","Run a per-builder uniqueness check that includes host/service/method extra keys."],"exampleFix":"// before\n\"constant_keys\": {\"host\":\"fixed\"},\n\"extra_keys\": {\"host\":\"host\"}\n// after\n\"constant_keys\": {\"host\":\"fixed\"},\n\"extra_keys\": {\"host\":\"client_host\"}","handlingStrategy":"validation","validationCode":"func validateExtraKeysUnique(kb *rlspb.GrpcKeyBuilder) error {\n    seen := map[string]bool{}\n    for k := range kb.GetConstantKeys() { seen[k] = true }\n    for _, h := range kb.GetHeaders() { seen[h.GetKey()] = true }\n    if h := kb.GetExtraKeys().GetHost(); h != \"\" && seen[h] {\n        return fmt.Errorf(\"extra_keys.host %q duplicates a constant/header key\", h)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Namespace host-derived keys (e.g. \"client_host\") to avoid clashing with header/constant keys.","Run an extra_keys overlap check for host, service, and method in CI.","Document your key vocabulary per builder so names do not collide."],"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"}