{"record":{"id":"678ff82cd0fc3db1","repo":"grpc/grpc-go","slug":"rls-invalid-target-uri-in-lookup-service-s","errorCode":null,"errorMessage":"rls: invalid target URI in lookup_service %s","messagePattern":"rls: invalid target URI in lookup_service (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/rls/config.go","lineNumber":203,"sourceCode":"\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 {\n\t\treturn nil, fmt.Errorf(\"rls: failed to parse lookup_service_timeout in route lookup config %+v: %v\", rlsProto, err)\n\t}\n\tif lookupServiceTimeout == 0 {\n\t\tlookupServiceTimeout = defaultLookupServiceTimeout\n\t}\n\n\t// Validations performed here:","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/rls/config.go#L185-L221","documentation":"Returned by parseRLSProto (config.go:198-204) when lookup_service cannot be parsed as a target URI even after prefixing the default scheme (resolver.GetDefaultScheme() + \":///\"). url.Parse failed both on the raw value and on the default-scheme-prefixed value, so the string is not a usable dial target.","triggerScenarios":"lookup_service contains characters that make it an invalid URI even with a scheme prepended (control characters, malformed escaping). The first url.Parse fails (typically because the scheme is missing), and the retry with the default scheme also fails.","commonSituations":"Typo or stray characters in the RLS server address. Pasting an address with embedded spaces or unescaped special characters. Control-plane templating bug injecting bad bytes.","solutions":["Provide a clean host[:port] or a fully-qualified target URI for lookup_service (e.g. \"dns:///rls.example:443\").","Sanitize the address string and re-test with url.Parse before shipping the config.","Check the xDS control plane's lookup_service field for corruption."],"exampleFix":"// before\nrlc.LookupService = \"rls example:443\" // space makes it un-parseable\n\n// after\nrlc.LookupService = \"dns:///rls.example:443\"","handlingStrategy":"validation","validationCode":"import \"net/url\"\nimport \"google.golang.org/grpc/resolver\"\n\nfunc validateLookupServiceURI(svc string) error {\n    t, err := url.Parse(svc)\n    if err != nil {\n        t, err = url.Parse(resolver.GetDefaultScheme() + \":///\" + svc)\n        if err != nil {\n            return fmt.Errorf(\"invalid target URI %s\", svc)\n        }\n    }\n    _ = t\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use clean host[:port] or dns:///host:port forms.","Sanitize addresses before putting them in the config."],"tags":["go","grpc","load-balancing","rls","config","resolver"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}