windmill-labs/windmill · error
HTTP proxy CONNECT to {} rejected: {}
Error message
HTTP proxy CONNECT to {} rejected: {} What it means
`http_connect_tunnel` sends an HTTP `CONNECT host:port` request and then parses the proxy's response. If the status line is not a 2xx success (per the `status_ok` check), the proxy refused to open the tunnel, and the function returns the proxy's own status line (e.g. `HTTP/1.1 407 Proxy Authentication Required`) embedded in this io::Error message.
Source
Thrown at backend/windmill-trigger-websocket/src/proxy.rs:293
));
}
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;
}
}
if !status_ok {
return Err(io::Error::new(
io::ErrorKind::Other,
format!(
"HTTP proxy CONNECT to {} rejected: {}",
host_header,
status_line.trim_end()
),
));
}
// A conforming proxy stays silent after the CONNECT response until the
// client speaks. If our read buffer is non-empty, the proxy spoke
// first — handing the raw socket to TLS would silently drop those
// bytes and break the handshake.
if !reader.buffer().is_empty() {
return Err(io::Error::new(
io::ErrorKind::Other,
"HTTP proxy sent unexpected bytes after CONNECT response",
));View on GitHub (pinned to e474e8803c)
Solutions
- Read the status in the message: 407 → add/fix proxy credentials (user:pass), 403 → request allowlisting of the target host on the proxy, 5xx → check the proxy's outbound connectivity to the target
- Supply proxy credentials in the proxy URL (`http://user:pass@proxy:port`) so basic auth is forwarded
- Verify the target websocket host:port is reachable from the proxy host itself (e.g. `curl https://target -v` from the proxy machine)
- Check proxy access logs for the exact CONNECT denial reason
Example fix
// before let proxy = "http://proxy.corp:3128"; // 407 Proxy Authentication Required // after let proxy = "http://user:pass@proxy.corp:3128";
Defensive patterns
Strategy: try-catch
Validate before calling
// preflight CONNECT to catch 407/403 before the websocket call
let status = probe_proxy_connect(proxy_url, target_host, target_port).await?;
if !status.is_2xx() {
return Err(anyhow!("proxy CONNECT preflight failed with {status}"));
} Try / catch
match connect_async_with_proxy(&url, &proxy).await {
Err(WsError::Io(e)) if e.to_string().contains("rejected") => {
if e.to_string().contains("407") {
eprintln!("proxy auth failed: embed credentials in proxy URL (http://user:pass@proxy)");
}
// else: log the embedded status line, check proxy ACLs/target reachability
}
Err(e) => return Err(e.into()),
Ok(_) => {}
} Prevention
- Always include credentials in the proxy URL when the proxy requires auth (http://user:pass@host:port)
- Allowlist websocket target hosts on the corporate proxy before deploying workers
- Test CONNECT through the proxy to each target host during deployment checks
- Parse the embedded status line (407/403/5xx) in monitoring to distinguish auth vs policy vs upstream failures
When it happens
Trigger: Calling `connect_async_with_proxy` (via `test_connection` or `get_consumer`) when the HTTP proxy answers the CONNECT request with a non-2xx status — typically 407 (auth required), 403 (denied), or 502/503 (cannot reach target).
Common situations: Missing or wrong proxy credentials (407); corporate proxy blocks the destination host (403); target websocket host unreachable from the proxy's network (502/504); proxy misconfigured to require auth while client sends none.
Related errors
- HTTP proxy closed connection before sending CONNECT response
- HTTP proxy sent unexpected bytes after CONNECT response
- Got an HTML response from ${url} (status ${status}${cfPart ?
- Failed to fetch foundation models for AWS Bedrock
- Failed to fetch models for provider ${provider}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/aa2fa52f300f0f8d.
Report an issue: GitHub.