{"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/0c51461d27177d997e14c642fe18c11668fc09a3/internal/resolver/delegatingresolver/delegatingresolver.go#L408-L444","documentation":"After the target resolver returns TCP addresses that need a proxy, the delegating resolver lazily builds a DNS resolver for the proxy host via proxyURIResolver (delegatingresolver.go:417-430). Unlike construction errors for the target resolver, this failure is reported asynchronously through r.cc.ReportError rather than returned from New(), because it happens in a goroutine after New() has already returned.","triggerScenarios":"Triggered when r.proxyURIResolver(resolver.BuildOptions{}) returns an error inside the goroutine spawned by updateTargetResolverState. This is the \"dns\" scheme resolver failing to Build for the proxy host URL.","commonSituations":"The proxy URL host is empty or malformed in a way the DNS resolver builder rejects, the \"dns\" resolver was unregistered (would panic earlier), or BuildOptions are insufficient. Rare in practice because the proxy URL was already validated; usually a sign of an exotic proxy URL shape.","solutions":["Watch for errors via grpclog / the ClientConn error handler (this is delivered through ReportError, not returned from Dial).","Verify the HTTPS_PROXY host component is a resolvable DNS name or IP.","Simplify the proxy URL (scheme + host + port only) and remove exotic components.","Temporarily disable the proxy (unset HTTPS_PROXY, add the target to NO_PROXY) to confirm the proxy is the source."],"exampleFix":"# before\nexport HTTPS_PROXY='http:///path'   # malformed, no host\n\n# after\nexport HTTPS_PROXY='http://proxy.corp:3128'","handlingStrategy":"validation","validationCode":"package main\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\t\"os\"\n)\n\n// Check the proxy URL host is a plausible DNS name / IP before the resolver\n// tries to build a DNS resolver for it.\nfunc validateProxyHost() error {\n\traw := os.Getenv(\"HTTPS_PROXY\")\n\tif raw == \"\" {\n\t\treturn nil\n\t}\n\tu, err := url.Parse(raw)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"HTTPS_PROXY unparseable: %w\", err)\n\t}\n\tif u.Host == \"\" {\n\t\treturn fmt.Errorf(\"HTTPS_PROXY has no host\")\n\t}\n\treturn nil\n}\n\n// func main() { _ = validateProxyHost }","typeGuard":null,"tryCatchPattern":"// This error is delivered asynchronously via the ClientConn error handler,\n// NOT returned from Dial. Subscribe via grpc.WithReturnConnectionError or\n// WaitForStateChange/GetState.\n//\n//   conn.WaitForStateChange(ctx, connectivity.Idle)\n//   if state := conn.GetState(); state == connectivity.TransientFailure {\n//       // proxy resolver build failed; check HTTPS_PROXY and logs.\n//   }","preventionTips":["Keep HTTPS_PROXY as scheme://host:port only.","Log connection-state transitions so async resolver errors are visible.","Confirm the proxy host resolves (nslookup) before relying on it."],"tags":["resolver","delegating-resolver","proxy","dns","async","grpc"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}