{"record":{"id":"72c91b26ace740bf","repo":"grpc/grpc-go","slug":"could-not-get-resolver-for-default-scheme-q","errorCode":null,"errorMessage":"could not get resolver for default scheme: %q","messagePattern":"could not get resolver for default scheme: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"clientconn.go","lineNumber":1854,"sourceCode":"\t// We are here because the user's dial target did not contain a scheme or\n\t// specified an unregistered scheme. We should fallback to the default\n\t// scheme, except when a custom dialer is specified in which case, we should\n\t// always use passthrough scheme. For either case, we need to respect any overridden\n\t// global defaults set by the user.\n\tdefScheme := cc.dopts.defaultScheme\n\tif internal.UserSetDefaultScheme {\n\t\tdefScheme = resolver.GetDefaultScheme()\n\t}\n\n\tcanonicalTarget := defScheme + \":///\" + cc.target\n\n\tparsedTarget, err = parseTarget(canonicalTarget)\n\tif err != nil {\n\t\treturn err\n\t}\n\trb = cc.getResolver(parsedTarget.URL.Scheme)\n\tif rb == nil {\n\t\treturn fmt.Errorf(\"could not get resolver for default scheme: %q\", parsedTarget.URL.Scheme)\n\t}\n\tcc.parsedTarget = parsedTarget\n\tcc.resolverBuilder = rb\n\treturn nil\n}\n\n// parseTarget uses RFC 3986 semantics to parse the given target into a\n// resolver.Target struct containing url. Query params are stripped from the\n// endpoint.\nfunc parseTarget(target string) (resolver.Target, error) {\n\tu, err := url.Parse(target)\n\tif err != nil {\n\t\treturn resolver.Target{}, err\n\t}\n\n\treturn resolver.Target{URL: *u}, nil\n}\n","sourceCodeStart":1836,"sourceCodeEnd":1872,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/clientconn.go#L1836-L1872","documentation":"In initParsedTargetAndResolverBuilder (clientconn.go:1852-1854), when the dial target had no scheme or an unregistered scheme, gRPC falls back to the default scheme and re-parses. If getResolver() still returns nil for that fallback scheme, the channel cannot proceed. The %q is the fallback scheme string that has no registered builder.","triggerScenarios":"Dialing with a bare target (no scheme) when the default scheme's resolver isn't registered, or explicitly using a scheme with no builder. Common after switching default scheme via UserSetDefaultScheme to something unregistered.","commonSituations":"Forgetting to register a custom resolver; setting a custom default scheme that has no builder; running a minimal binary that didn't import the dns resolver.","solutions":["Register a resolver builder for the scheme shown in the error (resolver.Register), or import the package that registers it.","Prefix the target with a registered scheme such as dns:/// or passthrough:///.","If you set a custom default scheme, ensure its builder is registered before Dial."],"exampleFix":"// before\nconn, err := grpc.NewClient(\"myservice:443\")\n// after\nimport _ \"google.golang.org/grpc/internal/resolver/dns\"\nconn, err := grpc.NewClient(\"dns:///myservice:443\")","handlingStrategy":"validation","validationCode":"// Confirm a builder is registered for the effective scheme.\nfunc checkScheme(scheme string) error {\n    for _, s := range resolver.GetSchemes() { if s == scheme { return nil } }\n    return fmt.Errorf(\"unregistered scheme: %q\", scheme)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always prefix dial targets with an explicit, registered scheme (dns:///, passthrough:///).","If you override the default scheme, register its builder first.","Fail fast at startup with a scheme check rather than at dial time."],"tags":["go","grpc","resolver","clientconn","target"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}