{"record":{"id":"aa2fa52f300f0f8d","repo":"windmill-labs/windmill","slug":"http-proxy-connect-to-rejected","errorCode":null,"errorMessage":"HTTP proxy CONNECT to {} rejected: {}","messagePattern":"HTTP proxy CONNECT to (.+?) rejected: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-trigger-websocket/src/proxy.rs","lineNumber":293,"sourceCode":"        ));\n    }\n\n    let status_ok = status_line\n        .split_whitespace()\n        .nth(1)\n        .map(|s| s == \"200\")\n        .unwrap_or(false);\n\n    loop {\n        let mut line = String::new();\n        let n = reader.read_line(&mut line).await?;\n        if n == 0 || line == \"\\r\\n\" || line == \"\\n\" {\n            break;\n        }\n    }\n\n    if !status_ok {\n        return Err(io::Error::new(\n            io::ErrorKind::Other,\n            format!(\n                \"HTTP proxy CONNECT to {} rejected: {}\",\n                host_header,\n                status_line.trim_end()\n            ),\n        ));\n    }\n\n    // A conforming proxy stays silent after the CONNECT response until the\n    // client speaks. If our read buffer is non-empty, the proxy spoke\n    // first — handing the raw socket to TLS would silently drop those\n    // bytes and break the handshake.\n    if !reader.buffer().is_empty() {\n        return Err(io::Error::new(\n            io::ErrorKind::Other,\n            \"HTTP proxy sent unexpected bytes after CONNECT response\",\n        ));","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-trigger-websocket/src/proxy.rs#L275-L311","documentation":"`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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nlet proxy = \"http://proxy.corp:3128\"; // 407 Proxy Authentication Required\n// after\nlet proxy = \"http://user:pass@proxy.corp:3128\";","handlingStrategy":"try-catch","validationCode":"// preflight CONNECT to catch 407/403 before the websocket call\nlet status = probe_proxy_connect(proxy_url, target_host, target_port).await?;\nif !status.is_2xx() {\n    return Err(anyhow!(\"proxy CONNECT preflight failed with {status}\"));\n}","typeGuard":null,"tryCatchPattern":"match connect_async_with_proxy(&url, &proxy).await {\n    Err(WsError::Io(e)) if e.to_string().contains(\"rejected\") => {\n        if e.to_string().contains(\"407\") {\n            eprintln!(\"proxy auth failed: embed credentials in proxy URL (http://user:pass@proxy)\");\n        }\n        // else: log the embedded status line, check proxy ACLs/target reachability\n    }\n    Err(e) => return Err(e.into()),\n    Ok(_) => {}\n}","preventionTips":["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"],"tags":["network","proxy","http-connect","auth"],"backgroundTag":"proxy-connect-rejected","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}