{"record":{"id":"477117fd0cb393e1","repo":"grpc/grpc-go","slug":"delegating-resolver-unable-to-build-the-resolver","errorCode":null,"errorMessage":"delegating_resolver: unable to build the resolver for target %s: %v","messagePattern":"delegating_resolver: unable to build the resolver for target (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/resolver/delegatingresolver/delegatingresolver.go","lineNumber":158,"sourceCode":"\tr.childMu.Lock()\n\tdefer r.childMu.Unlock()\n\t// When the scheme is 'dns' and target resolution on client is not enabled,\n\t// resolution should be handled by the proxy, not the client. Therefore, we\n\t// bypass the target resolver and store the unresolved target address.\n\tif target.URL.Scheme == \"dns\" && !targetResolutionEnabled {\n\t\tr.targetResolverState = &resolver.State{\n\t\t\tAddresses: []resolver.Address{{Addr: addr}},\n\t\t\tEndpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: addr}}}},\n\t\t}\n\t\tr.updateTargetResolverState(*r.targetResolverState)\n\t\treturn r, nil\n\t}\n\twcc := &wrappingClientConn{\n\t\tstateListener: r.updateTargetResolverState,\n\t\tparent:        r,\n\t}\n\tif r.targetResolver, err = targetResolverBuilder.Build(target, wcc, opts); err != nil {\n\t\treturn nil, fmt.Errorf(\"delegating_resolver: unable to build the resolver for target %s: %v\", target, err)\n\t}\n\treturn r, nil\n}\n\n// proxyURIResolver creates a resolver for resolving proxy URIs using the \"dns\"\n// scheme. It adjusts the proxyURL to conform to the \"dns:///\" format and builds\n// a resolver with a wrappingClientConn to capture resolved addresses.\nfunc (r *delegatingResolver) proxyURIResolver(opts resolver.BuildOptions) (resolver.Resolver, error) {\n\tproxyBuilder := resolver.Get(\"dns\")\n\tif proxyBuilder == nil {\n\t\tpanic(\"delegating_resolver: resolver for proxy not found for scheme dns\")\n\t}\n\turl := *r.proxyURL\n\turl.Scheme = \"dns\"\n\turl.Path = \"/\" + r.proxyURL.Host\n\turl.Host = \"\" // Clear the Host field to conform to the \"dns:///\" format\n\n\tproxyTarget := resolver.Target{URL: url}","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/resolver/delegatingresolver/delegatingresolver.go#L140-L176","documentation":"After the proxy URL is resolved (or found unnecessary), the delegating resolver constructs the actual target resolver by calling targetResolverBuilder.Build(target, wcc, opts) at delegatingresolver.go:157. If the underlying scheme-specific resolver (dns, passthrough, unix, etc.) fails to build, New() wraps and returns the error.","triggerScenarios":"Triggered when targetResolverBuilder.Build returns a non-nil error during delegatingresolver.New while a proxy is configured (so the delegating resolver is in use) and target resolution is enabled.","commonSituations":"The scheme-specific resolver rejects the target (e.g. unix resolver sees a non-empty authority), a custom resolver registered via grpc.WithResolvers fails, or the target URI is malformed for the chosen scheme.","solutions":["Read the wrapped %v to identify which child resolver failed and why.","Validate the dial target string conforms to the scheme's expectations (e.g. \"unix:///path/to/socket\", \"dns:///host:port\").","If using a custom resolver via grpc.WithResolvers, ensure its Build does not error for the given target.","Test the target with the scheme's resolver directly to isolate the failure."],"exampleFix":"// before:\n//   conn, err := grpc.Dial(\"unix://localhost/tmp/x.sock\", opts)\n//   // unix resolver rejects non-empty authority \"localhost\"\n\n// after:\n//   conn, err := grpc.Dial(\"unix:///tmp/x.sock\", opts)","handlingStrategy":"try-catch","validationCode":"// If you register a custom resolver, smoke-test its Build before relying on\n// it in production.\n//\n//   b := resolver.Get(scheme)\n//   if b == nil { log.Fatalf(\"no resolver registered for scheme %q\", scheme) }\n//   r, err := b.Build(target, cc, opts)\n//   if err != nil { log.Fatalf(\"resolver build failed: %v\", err) }\n//   r.Close()","typeGuard":null,"tryCatchPattern":"// Dial surfaces the wrapped build error synchronously.\n//\n//   conn, err := grpc.Dial(target, opts)\n//   if err != nil {\n//       return fmt.Errorf(\"dial %s failed: %w\", target, err)\n//   }","preventionTips":["Validate the dial target against the scheme's expected format (unix path, dns host:port).","Unit-test custom resolvers' Build for the targets they will receive.","Log the exact target string when dial failures occur."],"tags":["resolver","delegating-resolver","addressing","configuration","grpc"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}