windmill-labs/windmill · error
HTTP proxy closed connection before sending CONNECT response
Error message
HTTP proxy closed connection before sending CONNECT response
What it means
`http_connect_tunnel` opens a plain TCP connection to the HTTP proxy, sends a `CONNECT host:port` request, then reads the status line of the proxy's response. If `read_line` returns `n == 0`, the proxy closed the TCP connection before answering the CONNECT request, so no tunnel can be established and the function converts this into `io::ErrorKind::UnexpectedEof`.
Source
Thrown at backend/windmill-trigger-websocket/src/proxy.rs:272
let mut stream = TcpStream::connect((proxy.host.as_str(), proxy.port)).await?;
let host_header = format!("{}:{}", target_host, target_port);
let mut req = format!("CONNECT {h} HTTP/1.1\r\nHost: {h}\r\n", h = host_header,);
if let Some(ref auth) = proxy.basic_auth {
req.push_str("Proxy-Authorization: Basic ");
req.push_str(auth);
req.push_str("\r\n");
}
req.push_str("Proxy-Connection: keep-alive\r\n\r\n");
stream.write_all(req.as_bytes()).await?;
stream.flush().await?;
let mut reader = BufReader::new(stream);
let mut status_line = String::new();
let n = reader.read_line(&mut status_line).await?;
if n == 0 {
return Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
"HTTP proxy closed connection before sending CONNECT response",
));
}
let status_ok = status_line
.split_whitespace()
.nth(1)
.map(|s| s == "200")
.unwrap_or(false);
loop {
let mut line = String::new();
let n = reader.read_line(&mut line).await?;
if n == 0 || line == "\r\n" || line == "\n" {
break;
}
}View on GitHub (pinned to e474e8803c)
Solutions
- Confirm the proxy speaks plain HTTP CONNECT on that port (e.g. `curl -x http://proxy:port https://target -v`); if it needs TLS, fix the scheme
- Check proxy ACLs/logs for denied CONNECT to the target host:port
- Verify the target host:port is allowed by the proxy's whitelist/allowlist config
- Test connectivity to the proxy itself (`nc -vz proxy port`) and check the proxy service logs for crashes or timeouts
Example fix
// before // client config: proxy = "http://proxy.corp:3128" but proxy requires TLS // after // proxy = "https://proxy.corp:3128" (or configure the proxy to accept plain CONNECT)
Defensive patterns
Strategy: try-catch
Validate before calling
// sanity-check the proxy speaks plain CONNECT before use
let mut s = tokio::net::TcpStream::connect((proxy_host, proxy_port)).await?;
s.write_all(b"CONNECT example.com:443 HTTP/1.1\r\nHost: example.com:443\r\n\r\n").await?;
let mut buf = vec![0u8; 16];
let n = s.read(&mut buf).await?;
if n == 0 { return Err(anyhow!("proxy closes connection on CONNECT - check proxy ACLs/TLS mode")); } Try / catch
match connect_async_with_proxy(&url, &proxy).await {
Err(WsError::Io(e)) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
eprintln!("proxy dropped the CONNECT request: {}", e);
// surface a config hint: wrong scheme (TLS vs plain), ACL denial, proxy down
}
Err(e) => return Err(e.into()),
Ok(_) => {}
} Prevention
- Verify the proxy URL scheme matches the listener (http:// for plain CONNECT, https:// for TLS proxies)
- Smoke-test the proxy with `curl -x http://proxy:port https://target -v` after config changes
- Keep proxy ACLs/allowlists in sync with the websocket targets your workers need
- Alert on proxy-side connection resets via proxy metrics/logs
When it happens
Trigger: Calling `connect_async_with_proxy` (via `test_connection` or `get_consumer`) where the configured HTTP proxy accepts the TCP connection but closes it immediately upon (or before) responding to the CONNECT request — e.g. proxy rejects the target, times out, or requires TLS on the proxy link.
Common situations: Proxy expects HTTPS (TLS) on the client link but gets plaintext CONNECT; proxy software (squid, mitmproxy, Istio sidecar) has an ACL denying the destination; idle/connection limits; proxy crashed between accept and respond.
Related errors
- HTTP proxy CONNECT to {} rejected: {}
- HTTP proxy sent unexpected bytes after CONNECT response
- Failed to fetch foundation models for AWS Bedrock
- Failed to fetch models for provider ${provider}
- Bad Gateway
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/671db890a5a0b35f.
Report an issue: GitHub.