{"record":{"id":"75002af6c89c9413","repo":"grpc/grpc-go","slug":"rls-unregistered-scheme-in-lookup-service-s","errorCode":null,"errorMessage":"rls: unregistered scheme in lookup_service %s","messagePattern":"rls: unregistered scheme in lookup_service (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/rls/config.go","lineNumber":210,"sourceCode":"\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:\n\t// - if `max_age` > 5m, it should be set to 5 minutes\n\t//   only if stale age is not set\n\t// - if `stale_age` > `max_age`, ignore it\n\t// - if `stale_age` is set, then `max_age` must also be set\n\tmaxAgeSet := false\n\tmaxAge, err := convertDuration(rlsProto.GetMaxAge())\n\tif err != nil {","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/balancer/rls/config.go#L192-L228","documentation":"Emitted from parseRLSProto (config.go:210) when the URI scheme parsed from lookup_service has no resolver registered via resolver.Get. The RLS balancer resolves the lookup_service address through the standard gRPC resolver machinery, so the scheme must correspond to a registered resolver (dns, passthrough, xds, unix, etc.).","triggerScenarios":"lookupService uses a scheme like 'foo:///' where 'foo' was never registered with resolver.Register, or uses a scheme whose resolver lives in a package the binary does not import.","commonSituations":"Using 'dns:///host' but the binary does not import the dns resolver (in older grpc versions) ; using a custom resolver scheme without blank-importing its package; a typo in the scheme ('gdns', 'xds2'); relying on xds-federation/experimental schemes that are not built into this binary.","solutions":["Use the default scheme by omitting the scheme (the balancer prepends resolver.GetDefaultScheme()), or use a scheme you know is registered.","Blank-import the resolver package providing the scheme, e.g. _ 'google.golang.org/grpc/resolver/dns' or _ 'google.golang.org/grpc/xds/internal/resolver'.","Register your custom resolver with resolver.Register before dialing if you have a proprietary scheme.","Switch to 'passthrough:///host:port' for tests or when the address is already resolved."],"exampleFix":"// before\n\"lookupService\": \"mydns:///rls.example.com:443\"  // mydns not registered\n\n// after\n\"lookupService\": \"dns:///rls.example.com:443\"\n// and ensure the binary imports the dns resolver if required by your grpc version","handlingStrategy":"validation","validationCode":"func validateLookupScheme(s string) error {\n    u, err := url.Parse(s)\n    if err != nil {\n        u, err = url.Parse(resolver.GetDefaultScheme() + \"/\" + s)\n        if err != nil {\n            return fmt.Errorf(\"lookup_service %q is not a valid URI\", s)\n        }\n    }\n    scheme := u.Scheme\n    if scheme == \"\" {\n        scheme = resolver.GetDefaultScheme()\n    }\n    if resolver.Get(scheme) == nil {\n        return fmt.Errorf(\"no resolver registered for scheme %q\", scheme)\n    }\n    return nil\n}","typeGuard":"func lookupSchemeIsRegistered(s string) bool {\n    u, _ := url.Parse(s)\n    scheme := u.Scheme\n    if scheme == \"\" {\n        scheme = resolver.GetDefaultScheme()\n    }\n    return resolver.Get(scheme) != nil\n}","tryCatchPattern":null,"preventionTips":["Blank-import the resolver package for any non-default scheme you reference.","Prefer 'dns:///host:port' or omit the scheme to use the default.","Register custom resolvers via resolver.Register before dialing."],"tags":["rls","resolver","lookup-service","validation"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}