grpc/grpc-go · warning

delegating_resolver: unable to build the proxy resolver: %v

Error message

delegating_resolver: unable to build the proxy resolver: %v

What it means

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.

Source

Thrown at internal/resolver/delegatingresolver/delegatingresolver.go:426

	// type, or are listed in the `NO_PROXY` environment variable, do not wait
	// for proxy update.
	if !needsProxyResolver(r.targetResolverState) {
		return r.cc.UpdateState(*r.targetResolverState)
	}

	// The proxy resolver may be rebuilt multiple times, specifically each time
	// the target resolver sends an update, even if the target resolver is built
	// successfully but building the proxy resolver fails.
	if len(r.proxyAddrs) == 0 {
		go func() {
			r.childMu.Lock()
			defer r.childMu.Unlock()
			if _, ok := r.proxyResolver.(nopResolver); !ok {
				return
			}
			proxyResolver, err := r.proxyURIResolver(resolver.BuildOptions{})
			if err != nil {
				r.cc.ReportError(fmt.Errorf("delegating_resolver: unable to build the proxy resolver: %v", err))
				return
			}
			r.proxyResolver = proxyResolver
		}()
	}

	err := r.updateClientConnStateLocked()
	if err != nil {
		go func() {
			r.childMu.Lock()
			defer r.childMu.Unlock()
			if r.proxyResolver != nil {
				r.proxyResolver.ResolveNow(resolver.ResolveNowOptions{})
			}
		}()
	}
	return nil
}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Ensure HTTPS_PROXY is a valid, resolvable host (e.g. http://proxy.corp:3128).
  2. Check that the proxy hostname resolves via DNS at the time of dial.
  3. Monitor cc error reports; this is transient and the resolver retries, but a persistent failure means the proxy config is wrong.

Example fix

// before
export HTTPS_PROXY=http://:3128   // empty host -> proxy resolver build fails
// after
export HTTPS_PROXY=http://proxy.corp:3128
Defensive patterns

Strategy: retry

Validate before calling

// Validate proxy URL host is non-empty and resolvable-looking.
if u, err := url.Parse(os.Getenv("HTTPS_PROXY")); err == nil && u.Host == "" {
    return errors.New("HTTPS_PROXY has empty host")
}

Try / catch

// Reported asynchronously via cc.ReportError; observe it and let the resolver retry,
// or surface it to monitoring.
// (No synchronous catch; the resolver self-heals on the next target update.)

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


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