nats-io/nats-server · error
failed to connect to proxy: %v
Error message
failed to connect to proxy: %v
What it means
The TCP connection to the HTTP proxy server failed during leafnode remote connection. natsDialTimeout could not establish a socket to proxyAddr.Host within the configured proxy timeout, so the CONNECT tunnel cannot even begin. The wrapped error carries the underlying OS/network cause (timeout, connection refused, DNS failure).
Source
Thrown at server/leafnode.go:632
if s.leafNodeOpts.dialer == nil {
s.leafNodeOpts.dialer = natsDialTimeout
}
}
const sharedSysAccDelay = 250 * time.Millisecond
// establishHTTPProxyTunnel establishes an HTTP CONNECT tunnel through a proxy server
func establishHTTPProxyTunnel(proxyURL, targetHost string, timeout time.Duration, username, password string) (net.Conn, error) {
proxyAddr, err := url.Parse(proxyURL)
if err != nil {
// This should not happen since proxy URL is validated during configuration parsing
return nil, fmt.Errorf("unexpected proxy URL parse error (URL was pre-validated): %v", err)
}
// Connect to the proxy server
conn, err := natsDialTimeout("tcp", proxyAddr.Host, timeout)
if err != nil {
return nil, fmt.Errorf("failed to connect to proxy: %v", err)
}
// Set deadline for the entire proxy handshake
if err := conn.SetDeadline(time.Now().Add(timeout)); err != nil {
conn.Close()
return nil, fmt.Errorf("failed to set deadline: %v", err)
}
req := &http.Request{
Method: http.MethodConnect,
URL: &url.URL{Opaque: targetHost}, // Opaque is required for CONNECT
Host: targetHost,
Header: make(http.Header),
}
// Add proxy authentication if provided
if username != "" && password != "" {
req.Header.Set("Proxy-Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password)))View on GitHub (pinned to 3a66a489d2)
Solutions
- Verify the proxy is reachable: nc -vz <proxy-host> <proxy-port> from the NATS server host
- Correct proxy_url host/port in the leafnode remote config
- Increase the proxy timeout value if latency is the issue
- Check DNS resolution and firewall/security-group rules for the proxy port
Example fix
// before
proxy {
url: "http://proxy-wrong-host:3128"
timeout: 1s
}
// after
proxy {
url: "http://proxy.internal:3128"
timeout: 10s
} Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", host, 3*time.Second)
if err != nil { return fmt.Errorf("proxy %s unreachable before start: %w", host, err) }
conn.Close() Try / catch
var conn net.Conn
err := retry.Do(func() error {
c, e := establishHTTPProxyTunnel(purl, target, timeout, user, pass)
if e != nil { return e }
conn = c
return nil
}, retry.OnRetry(func(n uint, err error) {
log.Printf("proxy dial attempt %d failed: %v", n+1, err)
})) Prevention
- Health-check the proxy port before starting the server
- Set proxy timeout above worst-case network RTT
- Monitor the proxy service; alert on unreachability
- Use stable DNS names and check firewall rules for the proxy port
When it happens
Trigger: establishHTTPProxyTunnel dials proxyAddr.Host and gets an error: proxy host unreachable, wrong host/port in proxy_url, proxy down, DNS not resolving, firewall dropping, or timeout too small for a slow network.
Common situations: Typos in proxy_url host/port; proxy service not running or listening only on localhost; container/DNS misconfiguration in Kubernetes; corporate firewall blocking the proxy port; proxy timeout set far below actual network latency.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- failed to set deadline: %v
- failed to write CONNECT request: %v
- failed to read proxy response: %v
- proxy CONNECT failed: %s
- no available OCSP servers
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/4d330da1cfece25b.
Report an issue: GitHub.