grpc/grpc-go · error
delegating_resolver: failed to determine proxy URL for…
Error message
delegating_resolver: failed to determine proxy URL for target %q: %v
What it means
Before building child resolvers, the delegating resolver determines whether a proxy applies by calling proxyURLForTarget(addr) which internally invokes http.ProxyFromEnvironment (delegatingresolver.go:86-92, 123-126). If that function returns a non-nil error (malformed HTTPS_PROXY/HTTP_PROXY URL), New() aborts with this wrapped error. A nil proxy URL with nil error simply means 'no proxy'.
Solutions
- Inspect the wrapped %v which usually comes from url.Parse and names the malformed component.
- Fix the HTTPS_PROXY/HTTP_PROXY value to be a fully-qualified URL, e.g. 'http://proxy.corp:3128'.
- If no proxy is intended, unset HTTPS_PROXY/HTTP_PROXY or add the target host to NO_PROXY.
- Restart the process after correcting env vars.
Example fix
# before export HTTPS_PROXY='proxy.corp:3128' # missing scheme # after export HTTPS_PROXY='http://proxy.corp:3128'
Defensive patterns
Strategy: validation
Validate before calling
package main
import (
"fmt"
"net/http"
"net/url"
"os"
)
func validateProxyEnv() error {
for _, kv := range os.Environ() {
// Inspect keys only, never print secret values.
name := kv
if i := indexOf(kv, '='); i >= 0 {
name = kv[:i]
}
if name != "HTTPS_PROXY" && name != "HTTP_PROXY" {
continue
}
}
req := &http.Request{URL: &url.URL{Scheme: "https", Host: "example.com"}}
if _, err := http.ProxyFromEnvironment(req); err != nil {
return fmt.Errorf("proxy env invalid: %w", err)
}
return nil
}
func indexOf(s, sub string) int {
for i := 0; i+len(sub) <= len(s); i++ {
if s[i:i+len(sub)] == sub {
return i
}
}
return -1
}
// func main() { _ = validateProxyEnv } Try / catch
// Dial fails synchronously with this wrapped error.
//
// conn, err := grpc.Dial(target, opts)
// if err != nil && strings.Contains(err.Error(), "failed to determine proxy URL") {
// // fix HTTPS_PROXY, then retry Dial
// } Prevention
- Always include the scheme in HTTPS_PROXY/HTTP_PROXY (e.g. http://host:port).
- Validate proxy env at process start with http.ProxyFromEnvironment against a sample URL.
- Document required proxy env format in deployment manifests.
When it happens
Trigger: Triggered when the HTTPS_PROXY (or HTTP_PROXY) environment variable is set to a value that cannot be parsed as a URL by net/url (e.g. missing scheme, embedded illegal characters), or http.ProxyFromEnvironment otherwise errors for the target address.
Common situations: Misconfigured proxy env vars in a container/systemd unit, a value like 'proxy.corp:3128' missing the 'http://' scheme, a typo or trailing space in HTTPS_PROXY, or a CI runner injecting a broken proxy URL.
Related errors
- delegating_resolver: invalid target address
- delegating_resolver: unable to build the proxy resolver
- delegating_resolver: unable to build the resolver for target
- missing address
- missing port after port-separator colon
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/bec2ebf8a6ed439d.
Report an issue: GitHub.
Appendix: source
Thrown at internal/resolver/delegatingresolver/delegatingresolver.go:125
r := &delegatingResolver{
target: target,
cc: cc,
proxyResolver: nopResolver{},
targetResolver: nopResolver{},
}
addr := target.Endpoint()
var err error
if target.URL.Scheme == "dns" && !targetResolutionEnabled && envconfig.EnableDefaultPortForProxyTarget {
addr, err = parseTarget(addr)
if err != nil {
return nil, fmt.Errorf("delegating_resolver: invalid target address %q: %v", target.Endpoint(), err)
}
}
r.proxyURL, err = proxyURLForTarget(addr)
if err != nil {
return nil, fmt.Errorf("delegating_resolver: failed to determine proxy URL for target %q: %v", target, err)
}
// proxy is not configured or proxy address excluded using `NO_PROXY` env
// var, so only target resolver is used.
if r.proxyURL == nil {
return targetResolverBuilder.Build(target, cc, opts)
}
if logger.V(2) {
logger.Infof("Proxy URL detected : %s", r.proxyURL)
}
// Resolver updates from one child may trigger calls into the other. Block
// updates until the children are initialized.
r.childMu.Lock()
defer r.childMu.Unlock()
// When the scheme is 'dns' and target resolution on client is not enabled,
// resolution should be handled by the proxy, not the client. Therefore, weView on GitHub (pinned to 0c51461d27)