{"record":{"id":"2e2a0d8c557295c4","repo":"grpc/grpc-go","slug":"rls-empty-lookup-service-in-route-lookup-config","errorCode":null,"errorMessage":"rls: empty lookup_service in route lookup config %+v","messagePattern":"rls: empty lookup_service in route lookup config %\\+v","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/rls/config.go","lineNumber":196,"sourceCode":"\t\treturn nil, err\n\t}\n\tlbCfg.childPolicyName = name\n\tlbCfg.childPolicyConfig = config\n\tlbCfg.childPolicyTargetField = cfgJSON.ChildPolicyConfigTargetFieldName\n\treturn lbCfg, nil\n}\n\nfunc parseRLSProto(rlsProto *rlspb.RouteLookupConfig) (*lbConfig, error) {\n\t// Validations specified on the `grpc_keybuilders` field are performed here.\n\tkbMap, err := keys.MakeBuilderMap(rlsProto)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// `lookup_service` field must be set and must parse as a target URI.\n\tlookupService := rlsProto.GetLookupService()\n\tif lookupService == \"\" {\n\t\treturn nil, fmt.Errorf(\"rls: empty lookup_service in route lookup config %+v\", rlsProto)\n\t}\n\tparsedTarget, err := url.Parse(lookupService)\n\tif err != nil {\n\t\t// url.Parse() fails if scheme is missing. Retry with default scheme.\n\t\tparsedTarget, err = url.Parse(resolver.GetDefaultScheme() + \":///\" + lookupService)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"rls: invalid target URI in lookup_service %s\", lookupService)\n\t\t}\n\t}\n\tif parsedTarget.Scheme == \"\" {\n\t\tparsedTarget.Scheme = resolver.GetDefaultScheme()\n\t}\n\tif resolver.Get(parsedTarget.Scheme) == nil {\n\t\treturn nil, fmt.Errorf(\"rls: unregistered scheme in lookup_service %s\", lookupService)\n\t}\n\n\tlookupServiceTimeout, err := convertDuration(rlsProto.GetLookupServiceTimeout())\n\tif err != nil {","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/rls/config.go#L178-L214","documentation":"Returned by parseRLSProto (config.go:194-197) when RouteLookupConfig.lookup_service is empty. lookup_service is the RLS server address the policy dials to resolve targets; an empty value leaves RLS unable to function, so it is mandatory per the validation contract documented above ParseConfig.","triggerScenarios":"The RouteLookupConfig proto has lookup_service unset/empty (default proto value).","commonSituations":"Control plane emitting an RLS config before the RLS server address is known. Hand-authored proto with lookup_service omitted.","solutions":["Set lookup_service to the URI/authority of your RLS server (e.g. \"rls.example:443\" or \"dns:///rls.example:443\").","Confirm the control plane populates RouteLookupConfig.lookup_service from the xDS RLS Cluster resource."],"exampleFix":"// before\nrlc := &rlspb.RouteLookupConfig{ /* lookup_service missing */ }\n\n// after\nrlc := &rlspb.RouteLookupConfig{ LookupService: \"dns:///rls.example:443\" }","handlingStrategy":"validation","validationCode":"func validateLookupService(rlc *rlspb.RouteLookupConfig) error {\n    if rlc.GetLookupService() == \"\" {\n        return errors.New(\"lookup_service must be set\")\n    }\n    return nil\n}","typeGuard":"func hasLookupService(rlc *rlspb.RouteLookupConfig) bool { return rlc.GetLookupService() != \"\" }","tryCatchPattern":null,"preventionTips":["Always populate lookup_service with the RLS server address.","Fail fast in config construction if the RLS address is unknown."],"tags":["go","grpc","load-balancing","rls","config"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}