nats-io/nats-server · error
proxy CONNECT failed: %s
Error message
proxy CONNECT failed: %s
What it means
The proxy answered the CONNECT request with a non-200 status (e.g. 403 Forbidden, 407 Proxy Authentication Required, 502 Bad Gateway). The tunnel establishment is aborted with the proxy's own status line, so the NATS server cannot reach the target leafnode through the proxy.
Source
Thrown at server/leafnode.go:667
if username != "" && password != "" {
req.Header.Set("Proxy-Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password)))
}
if err := req.Write(conn); err != nil {
conn.Close()
return nil, fmt.Errorf("failed to write CONNECT request: %v", err)
}
resp, err := http.ReadResponse(bufio.NewReader(conn), req)
if err != nil {
conn.Close()
return nil, fmt.Errorf("failed to read proxy response: %v", err)
}
if resp.StatusCode != http.StatusOK {
resp.Body.Close()
conn.Close()
return nil, fmt.Errorf("proxy CONNECT failed: %s", resp.Status)
}
// Close the response body
resp.Body.Close()
// Clear the deadline now that we've finished the proxy handshake
if err := conn.SetDeadline(time.Time{}); err != nil {
conn.Close()
return nil, fmt.Errorf("failed to clear deadline: %v", err)
}
return conn, nil
}
// Connect to a remote leaf node asynchronously (that is, this function will do
// the connect in a go routine).
func (s *Server) connectToRemoteLeafNodeAsynchronously(remote *leafNodeCfg, firstConnect bool) {
remote.setConnectInProgress(true)View on GitHub (pinned to 3a66a489d2)
Solutions
- Add matching proxy username/password to the remote config if the status is 407
- Check proxy ACLs/firewall rules to allow the target leafnode host:port (403)
- Diagnose the proxy→target leg if the status is 502/504 (target down, DNS, egress rules)
- Read the %s status string in the error to identify the exact proxy response
Example fix
// before
proxy {
url: "http://proxy:3128"
}
// after (407 fix)
proxy {
url: "http://proxy:3128"
username: "user"
password: "pass"
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: verify credentials and target reachability via proxy curl -x http://user:pass@proxy:3128 https://leaf.example.com:443 -I
Try / catch
_, err := establishHTTPProxyTunnel(purl, target, timeout, user, pass)
if err != nil && strings.Contains(err.Error(), "proxy CONNECT failed") {
switch {
case strings.Contains(err.Error(), "407"):
log.Error("proxy needs credentials — set proxy username/password")
case strings.Contains(err.Error(), "403"):
log.Error("proxy denies target — update proxy ACLs")
default:
log.Errorf("proxy cannot reach target: %v", err)
}
} Prevention
- Configure proxy credentials whenever the proxy requires auth
- Whitelist the leafnode host:port in proxy ACLs
- Check the proxy can resolve and reach the target host
- Parse the returned HTTP status in logs to drive remediation
When it happens
Trigger: resp.StatusCode != http.StatusOK after http.ReadResponse in establishHTTPProxyTunnel: 407 means missing/wrong proxy credentials; 403 means the proxy forbids the target or source; 502/504 mean the proxy cannot reach the target host.
Common situations: Proxy requiring auth but no username/password configured (407); proxy ACLs blocking the destination host:port (403); target leafnode down or unreachable from the proxy (502/504); corporate proxies whitelisting only certain destinations.
Related errors
- failed to read proxy response: %v
- could not fetch <%q>: %v
- proxy username and password must both be specified or both b
- failed to connect to proxy: %v
- failed to set deadline: %v
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/09c6f9389e470415.
Report an issue: GitHub.