{"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/0c51461d27177d997e14c642fe18c11668fc09a3/balancer/rls/internal/keys/builder.go#L48-L84","documentation":"GrpcKeyBuilder.extra_keys lets you add the request host (extra_keys.host) as a key in the RLS request. grpc-go requires the host key name to differ from every key already claimed by constant_keys or headers (builder.go:65-66). If extra_keys.host equals an existing key in seenKeys, MakeBuilderMap rejects the config.","triggerScenarios":"A GrpcKeyBuilder has extra_keys.host = \"host\" while constant_keys or a header already uses the key name \"host\". The check at builder.go:65 finds it in seenKeys and returns this error.","commonSituations":"Adding host as an extra key after a constant key or header already claimed the name \"host\"; copying a template config and forgetting to namespace the extra_keys.","solutions":["Pick a distinct name for extra_keys.host (e.g., \"rpc_host\") that is not used by any constant_key or header.","Or remove the constant_key/header that collides if the host value should override it."],"exampleFix":"// before\nkb := &rlspb.GrpcKeyBuilder{\n  ConstantKeys: map[string]string{\"host\": \"localhost\"},\n  ExtraKeys:    &rlspb.GrpcKeyBuilder_ExtraKeys{Host: \"host\"},\n}\n// after\nkb := &rlspb.GrpcKeyBuilder{\n  ConstantKeys: map[string]string{\"host\": \"localhost\"},\n  ExtraKeys:    &rlspb.GrpcKeyBuilder_ExtraKeys{Host: \"rpc_host\"}, // distinct name\n}","handlingStrategy":"validation","validationCode":"func validateExtraKeysUnique(cfg *rlspb.RouteLookupConfig) error {\n\tfor _, kb := range cfg.GetGrpcKeybuilders() {\n\t\tseen := map[string]bool{}\n\t\tfor k := range kb.GetConstantKeys() { seen[k] = true }\n\t\tfor _, h := range kb.GetHeaders() { seen[h.GetKey()] = true }\n\t\tif h := kb.GetExtraKeys().GetHost(); h != \"\" && seen[h] {\n\t\t\treturn fmt.Errorf(\"extra_keys.host %q duplicates a constant/header key\", h)\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Namespace extra_keys fields (e.g., rpc_host, rpc_service, rpc_method) to avoid colliding with header/constant key names.","When adding extra_keys to an existing builder, re-check constant_keys and headers for collisions.","Test the config through keys.MakeBuilderMap."],"tags":["go","grpc","rls","config","validation","balancer"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}