{"record":{"id":"8d75cefd9106b3f5","repo":"grpc/grpc-go","slug":"delegating-resolver-unable-to-build-the-proxy-res","errorCode":null,"errorMessage":"delegating_resolver: unable to build the proxy resolver: %v","messagePattern":"delegating_resolver: unable to build the proxy resolver: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/resolver/delegatingresolver/delegatingresolver.go","lineNumber":426,"sourceCode":"\t// type, or are listed in the `NO_PROXY` environment variable, do not wait\n\t// for proxy update.\n\tif !needsProxyResolver(r.targetResolverState) {\n\t\treturn r.cc.UpdateState(*r.targetResolverState)\n\t}\n\n\t// The proxy resolver may be rebuilt multiple times, specifically each time\n\t// the target resolver sends an update, even if the target resolver is built\n\t// successfully but building the proxy resolver fails.\n\tif len(r.proxyAddrs) == 0 {\n\t\tgo func() {\n\t\t\tr.childMu.Lock()\n\t\t\tdefer r.childMu.Unlock()\n\t\t\tif _, ok := r.proxyResolver.(nopResolver); !ok {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tproxyResolver, err := r.proxyURIResolver(resolver.BuildOptions{})\n\t\t\tif err != nil {\n\t\t\t\tr.cc.ReportError(fmt.Errorf(\"delegating_resolver: unable to build the proxy resolver: %v\", err))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tr.proxyResolver = proxyResolver\n\t\t}()\n\t}\n\n\terr := r.updateClientConnStateLocked()\n\tif err != nil {\n\t\tgo func() {\n\t\t\tr.childMu.Lock()\n\t\t\tdefer r.childMu.Unlock()\n\t\t\tif r.proxyResolver != nil {\n\t\t\t\tr.proxyResolver.ResolveNow(resolver.ResolveNowOptions{})\n\t\t\t}\n\t\t}()\n\t}\n\treturn nil\n}","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/resolver/delegatingresolver/delegatingresolver.go#L408-L444","documentation":"Reported (via cc.ReportError, not returned) by updateTargetResolverState when r.proxyURIResolver() fails to build the dns-based proxy resolver. Because this runs in a goroutine after New() has already returned, the error is surfaced asynchronously to the ClientConn's error listener rather than aborting dial. The client retries proxy resolution on subsequent target updates.","triggerScenarios":"The dns resolver builder returning an error while resolving the proxy host derived from HTTPS_PROXY; a proxy host that is unparseable or whose authority is invalid; the dns resolver not being registered (panic path, not this error).","commonSituations":"HTTPS_PROXY host portion is malformed or unresolvable at construction time; transient dns failure when the proxy host is first resolved; the proxy URL host being empty.","solutions":["Ensure HTTPS_PROXY is a valid, resolvable host (e.g. http://proxy.corp:3128).","Check that the proxy hostname resolves via DNS at the time of dial.","Monitor cc error reports; this is transient and the resolver retries, but a persistent failure means the proxy config is wrong."],"exampleFix":"// before\nexport HTTPS_PROXY=http://:3128   // empty host -> proxy resolver build fails\n// after\nexport HTTPS_PROXY=http://proxy.corp:3128","handlingStrategy":"retry","validationCode":"// Validate proxy URL host is non-empty and resolvable-looking.\nif u, err := url.Parse(os.Getenv(\"HTTPS_PROXY\")); err == nil && u.Host == \"\" {\n    return errors.New(\"HTTPS_PROXY has empty host\")\n}","typeGuard":null,"tryCatchPattern":"// Reported asynchronously via cc.ReportError; observe it and let the resolver retry,\n// or surface it to monitoring.\n// (No synchronous catch; the resolver self-heals on the next target update.)","preventionTips":["Use a fully-qualified proxy URL with a real host in HTTPS_PROXY.","Monitor ClientConn error reports for persistent proxy-resolver failures.","Ensure the proxy host is DNS-resolvable from the start."],"tags":["grpc","resolver","delegating-resolver","proxy","dns","transient"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}