nats-io/nats-server · error

failed to read proxy response: %v

Error message

failed to read proxy response: %v

What it means

Reading the proxy's HTTP response to the CONNECT request failed. http.ReadResponse returned an error — the proxy did not send a valid HTTP response before the deadline, closed the connection, or returned garbage that is not HTTP.

Source

Thrown at server/leafnode.go:661

		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)
	}

	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

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Confirm proxy_url uses the right scheme and the target is an HTTP CONNECT proxy (http:// for plain HTTP proxies)
  2. Increase the proxy timeout if responses are slow
  3. Capture traffic (tcpdump) to see what the proxy actually returns
  4. Check proxy logs for why it dropped the connection

Example fix

// before
proxy { url: "http://proxy:1080" }  // actually a SOCKS proxy
// after
proxy { url: "http://proxy:3128" }  // real HTTP proxy port
Defensive patterns

Strategy: validation

Validate before calling

c, err := net.DialTimeout("tcp", proxyHost, 3*time.Second)
if err != nil { return err }
fmt.Fprintf(c, "CONNECT %s:443 HTTP/1.1\r\nHost: %s:443\r\n\r\n", target, target)
buf := make([]byte, 128)
n, _ := c.Read(buf)
if !strings.HasPrefix(string(buf[:n]), "HTTP/") {
    return fmt.Errorf("%s:%s is not an HTTP CONNECT proxy", host, port)
}
c.Close()

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to read proxy response") {
    log.Errorf("proxy did not answer HTTP CONNECT: %v — check proxy type/scheme", err)
}

Prevention

When it happens

Trigger: establishHTTPProxyTunnel calls http.ReadResponse(bufio.NewReader(conn), req) and gets a parse/EOF/timeout error: endpoint is not actually an HTTP proxy, proxy hung up, response exceeded the deadline, or a TLS port (HTTPS) was targeted with an http:// proxy URL.

Common situations: Pointing proxy_url at a SOCKS or HTTPS-only proxy that never answers plain HTTP CONNECT; proxy behind an LB that silently drops idle connections; extremely slow proxy exceeding the deadline; DPI equipment mangling the stream.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/abbad08b30605fb9. Report an issue: GitHub.