{"record":{"id":"e7ad7d814faf663b","repo":"grpc/grpc-go","slug":"failed-to-do-connect-handshake-response-q","errorCode":null,"errorMessage":"failed to do connect handshake, response: %q","messagePattern":"failed to do connect handshake, response: %q","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/transport/proxy.go","lineNumber":89,"sourceCode":"\t\tp, _ := user.Password()\n\t\treq.Header.Add(proxyAuthHeaderKey, \"Basic \"+basicAuth(u, p))\n\t}\n\tif err := sendHTTPRequest(ctx, req, conn); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to write the HTTP request: %v\", err)\n\t}\n\n\tr := bufio.NewReader(conn)\n\tresp, err := http.ReadResponse(r, req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reading server HTTP response: %v\", err)\n\t}\n\tdefer resp.Body.Close()\n\tif resp.StatusCode != http.StatusOK {\n\t\tdump, err := httputil.DumpResponse(resp, true)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to do connect handshake, status code: %s\", resp.Status)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"failed to do connect handshake, response: %q\", dump)\n\t}\n\t// The buffer could contain extra bytes from the target server, so we can't\n\t// discard it. However, in many cases where the server waits for the client\n\t// to send the first message (e.g. when TLS is being used), the buffer will\n\t// be empty, so we can avoid the overhead of reading through this buffer.\n\tif r.Buffered() != 0 {\n\t\treturn &bufConn{Conn: conn, r: r}, nil\n\t}\n\treturn conn, nil\n}\n\n// proxyDial establishes a TCP connection to the specified address and performs an HTTP CONNECT handshake.\nfunc proxyDial(ctx context.Context, addr resolver.Address, grpcUA string, opts proxyattributes.Options) (net.Conn, error) {\n\tconn, err := internal.NetDialerWithTCPKeepalive().DialContext(ctx, \"tcp\", addr.Addr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn doHTTPConnectHandshake(ctx, conn, grpcUA, opts)","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/transport/proxy.go#L71-L107","documentation":"This error occurs in doHTTPConnectHandshake when the proxy returns a non-200 status to the CONNECT request and the full response was successfully dumped. The dumped response (headers + body) is included for diagnostics, showing exactly why the proxy refused the tunnel.","triggerScenarios":"The proxy responded to CONNECT with a non-200 status (e.g., 407, 502) and httputil.DumpResponse succeeded, so the complete HTTP response including headers and body is quoted in the error message.","commonSituations":"Proxy authentication failure (407 with Proxy-Authenticate header), upstream connectivity issue (502 with error page), proxy access policy rejection (403). Common in corporate environments with authenticated proxies.","solutions":["Read the dumped response in the error message to identify the proxy's refusal reason.","For 407 responses, provide valid proxy credentials in the HTTPS_PROXY URL.","For 502/503, ensure the target endpoint is reachable from the proxy's network.","For 403, verify the destination is allowed by proxy access control lists."],"exampleFix":"// before (broken): missing credentials → 407 Proxy Authentication Required\nos.Setenv(\"HTTPS_PROXY\", \"http://proxy:3128\")\n\n// after (valid): embedded credentials satisfy the 407 challenge\nos.Setenv(\"HTTPS_PROXY\", \"http://svcuser:s3cret@proxy:3128\")","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"connect handshake, response\") {\n    // parse the dumped response for status code\n    // 407 → fix credentials; 502 → upstream issue; 403 → policy block\n    log.Printf(\"proxy refused CONNECT: %v\", err)\n    // implement fallback to direct connection or alternate proxy\n}","preventionTips":["Read the dumped response body in the error to diagnose proxy refusal.","Keep proxy credentials current and rotated properly.","Monitor proxy access logs for refused CONNECT requests from gRPC clients."],"tags":["transport","proxy","http-connect","authentication","network","diagnostics"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}