{"record":{"id":"f5881d9febca5254","repo":"grpc/grpc-go","slug":"rls-grpckeybuilder-in-routelookupconfig-contains-f5881d","errorCode":null,"errorMessage":"rls: GrpcKeyBuilder in RouteLookupConfig contains a method with a slash {%+v}","messagePattern":"rls: GrpcKeyBuilder in RouteLookupConfig contains a method with a slash (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/rls/internal/keys/builder.go","lineNumber":94,"sourceCode":"\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\n\t// RouteLookupRequest proto expects a Go map.\n\tMap map[string]string\n\t// Str is the representation of an RLS key as a string, sorted by keys.","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/balancer/rls/internal/keys/builder.go#L76-L112","documentation":"A GrpcKeyBuilder.Name.Method must be a bare method name with no slashes, because grpc-go constructs the full path as \"/\"+Service+\"/\"+Method (builder.go:93-96). If Method itself contains a '/', the resulting path would be malformed (e.g., \"/svc/a/b\"), so the builder rejects it up front.","triggerScenarios":"A Name.Method value like \"Foo/Bar\" or a leading slash. strings.Contains(name.GetMethod(), \"/\") at builder.go:93 is true.","commonSituations":"Populating Method with the full path \"/service/method\" by mistake; copying a method string that already includes the service prefix; config generators that concatenate service + \"/\" + method into the Method field.","solutions":["Set Name.Method to only the method name without any slash (e.g., \"SayHello\").","Put the service portion into Name.Service instead."],"exampleFix":"// before\nkb.Names = []*rlspb.Name{{Service: \"my.pkg.Greeter\", Method: \"my.pkg.Greeter/SayHello\"}}\n// after\nkb.Names = []*rlspb.Name{{Service: \"my.pkg.Greeter\", Method: \"SayHello\"}}","handlingStrategy":"validation","validationCode":"func validateMethodNameNoSlash(cfg *rlspb.RouteLookupConfig) error {\n\tfor _, kb := range cfg.GetGrpcKeybuilders() {\n\t\tfor _, n := range kb.GetNames() {\n\t\t\tif strings.Contains(n.GetMethod(), \"/\") {\n\t\t\t\treturn fmt.Errorf(\"Name.Method %q must not contain '/'\", n.GetMethod())\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Name.Method is the bare method name only; never include the service prefix or slashes.","Generate Names from the .proto service definitions to avoid manual errors.","Run keys.MakeBuilderMap in a test."],"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"}