nats-io/nats-server · error
failed to set deadline: %v
Error message
failed to set deadline: %v
What it means
Setting the handshake deadline on the freshly opened proxy connection failed. The code calls conn.SetDeadline(time.Now().Add(timeout)) to bound the entire CONNECT exchange; a non-nil error (e.g. the conn is already closed or the underlying transport does not support deadlines) aborts the tunnel. This is rare and usually indicates a broken/aborted connection immediately after dial.
Source
Thrown at server/leafnode.go:638
// 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)))
}
if err := req.Write(conn); err != nil {
conn.Close()
return nil, fmt.Errorf("failed to write CONNECT request: %v", err)
}View on GitHub (pinned to 3a66a489d2)
Solutions
- Retry the connection — the socket was likely reset by the peer
- Inspect why the proxy/LB drops connections right after accept
- In tests, use deadline-capable pipes (net.Pipe wrapped) or a real listener
Defensive patterns
Strategy: retry
Try / catch
conn, err := establishHTTPProxyTunnel(purl, target, timeout, user, pass)
if err != nil {
if strings.Contains(err.Error(), "failed to set deadline") {
time.Sleep(backoff)
conn, err = establishHTTPProxyTunnel(purl, target, timeout, user, pass)
}
if err != nil { return err }
} Prevention
- Retry transient socket resets with backoff
- Investigate LB/tcwrap rules that accept then drop connections
- In tests use deadline-capable transports
When it happens
Trigger: conn.SetDeadline returning an error right after natsDialTimeout succeeded — connection reset/closed between dial and deadline set, or a custom net.Conn implementation without deadline support injected in tests.
Common situations: Proxy closing the socket instantly (port opened then dropped by an LB or tcpwrap); test doubles using pipe connections without deadline support; kernel-level connection aborts under load.
Related errors
- no interest
- no flow response
- proxy timeout must be >= 0
- failed to connect to proxy: %v
- failed to write CONNECT request: %v
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/d6190f4b9f745cf2.
Report an issue: GitHub.