grpc/grpc-go · error

delegating_resolver: failed to determine proxy URL for targe

Error message

delegating_resolver: failed to determine proxy URL for target %q: %v

What it means

Returned by New() when proxyURLForTarget(addr) (which calls http.ProxyFromEnvironment) returns an error. This happens when the HTTPS_PROXY/HTTP_PROXY environment variable is present but not a parseable URL, or NO_PROXY is malformed. The resolver cannot decide whether a proxy applies, so construction aborts.

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, we

View on GitHub (pinned to 03255a9237)

Solutions

  1. Make HTTPS_PROXY/HTTP_PROXY a fully-qualified URL: "http://proxy.corp:3128".
  2. Trim whitespace and stray quotes from proxy environment variables.
  3. If no proxy is needed, unset HTTPS_PROXY and HTTP_PROXY (and rely on NO_PROXY if needed).
  4. Validate the proxy URL with url.Parse at startup before dialing.

Example fix

// before
export HTTPS_PROXY=proxy.corp:3128   // unparseable -> error
// after
export HTTPS_PROXY=http://proxy.corp:3128
Defensive patterns

Strategy: validation

Validate before calling

// Validate proxy env vars at startup.
func checkProxy() error {
    for _, e := range []string{"HTTPS_PROXY", "HTTP_PROXY", "https_proxy", "http_proxy"} {
        if v := os.Getenv(e); v != "" {
            if _, err := url.Parse(v); err != nil {
                return fmt.Errorf("%s unparseable: %w", e, err)
            }
        }
    }
    return nil
}

Try / catch

conn, err := grpc.Dial(target, ...)
if err != nil && strings.Contains(err.Error(), "failed to determine proxy URL") {
    // Clear the bad proxy var and retry without a proxy.
    os.Unsetenv("HTTPS_PROXY")
}

Prevention

When it happens

Trigger: Setting HTTPS_PROXY to a value that is not a valid URL (e.g. missing scheme, unescaped spaces); setting http_proxy with a malformed authority; a NO_PROXY pattern that breaks url parsing in some Go versions.

Common situations: Proxy env var copied from a shell with stray quotes/whitespace; proxy string like "proxy.corp:3128" without the http:// scheme; CI that injects proxy vars in different formats across stages.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/bec2ebf8a6ed439d. Report an issue: GitHub.