{"record":{"id":"78b6e66c0ebdf4fa","repo":"grpc/grpc-go","slug":"rls-grpckeybuilder-in-routelookupconfig-contains-78b6e6","errorCode":null,"errorMessage":"rls: GrpcKeyBuilder in RouteLookupConfig contains a Name field with no Service {%+v}","messagePattern":"rls: GrpcKeyBuilder in RouteLookupConfig contains a Name field with no Service (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/rls/internal/keys/builder.go","lineNumber":91,"sourceCode":"\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.\n\t\tnames := kb.GetNames()\n\t\tif len(names) == 0 {\n\t\t\treturn nil, fmt.Errorf(\"rls: GrpcKeyBuilder in RouteLookupConfig does not contain any Name {%+v}\", kbs)\n\t\t}\n\t\tfor _, name := range names {\n\t\t\tif name.GetService() == \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"rls: GrpcKeyBuilder in RouteLookupConfig contains a Name field with no Service {%+v}\", kbs)\n\t\t\t}\n\t\t\tif strings.Contains(name.GetMethod(), `/`) {\n\t\t\t\treturn nil, fmt.Errorf(\"rls: GrpcKeyBuilder in RouteLookupConfig contains a method with a slash {%+v}\", kbs)\n\t\t\t}\n\t\t\tpath := \"/\" + name.GetService() + \"/\" + name.GetMethod()\n\t\t\tif _, ok := bm[path]; ok {\n\t\t\t\treturn nil, fmt.Errorf(\"rls: GrpcKeyBuilder in RouteLookupConfig contains repeated Name field {%+v}\", kbs)\n\t\t\t}\n\t\t\tbm[path] = b\n\t\t}\n\t}\n\treturn bm, nil\n}\n\n// KeyMap represents the RLS keys to be used for a request.\ntype KeyMap struct {\n\t// Map is the representation of an RLS key as a Go map. This is used when\n\t// an actual RLS request is to be sent out on the wire, since the","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/rls/internal/keys/builder.go#L73-L109","documentation":"Each Name in a GrpcKeyBuilder is a {service, method} pair where the library splits the request path as /service/method. An empty service makes the path malformed, so MakeBuilderMap requires name.GetService() != \"\" and rejects any Name lacking a service.","triggerScenarios":"A names entry like {\"method\":\"DoThing\"} with no service, or {\"service\":\"\",\"method\":\"DoThing\"}.","commonSituations":"Building Name protos programmatically and forgetting to set Service; confusing the fully-qualified path (which is split later) with the service field; bad xDS data.","solutions":["Set service to the fully-qualified gRPC service name (e.g. \"pkg.Svc\").","For a catch-all across a service, set method to \"\" (empty) while keeping service set.","Lint every Name to ensure service is non-empty."],"exampleFix":"// before\n{\"names\":[{\"method\":\"Get\"}]}\n// after\n{\"names\":[{\"service\":\"pkg.Svc\",\"method\":\"Get\"}]}","handlingStrategy":"validation","validationCode":"func validateNameService(cfg *rlspb.RouteLookupConfig) error {\n    for bi, kb := range cfg.GetGrpcKeybuilders() {\n        for ni, n := range kb.GetNames() {\n            if n.GetService() == \"\" {\n                return fmt.Errorf(\"keybuilder[%d].names[%d] missing service\", bi, ni)\n            }\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set the service field when constructing a Name.","Use empty method (not empty service) for whole-service matching.","Lint every Name for a non-empty service before deploying."],"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"}