{"record":{"id":"63e74f9f5c596feb","repo":"cloudflare/cloudflared","slug":"failed-to-send-reply-v","errorCode":null,"errorMessage":"Failed to send reply: %v","messagePattern":"Failed to send reply: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"socks/request_handler.go","lineNumber":45,"sourceCode":"func NewRequestHandler(dialer Dialer, accessPolicy *ipaccess.Policy) RequestHandler {\n\treturn &StandardRequestHandler{\n\t\tdialer:       dialer,\n\t\taccessPolicy: accessPolicy,\n\t}\n}\n\n// Handle processes and responds to socks5 commands\nfunc (h *StandardRequestHandler) Handle(req *Request, conn io.ReadWriter) error {\n\tswitch req.Command {\n\tcase connectCommand:\n\t\treturn h.handleConnect(conn, req)\n\tcase bindCommand:\n\t\treturn h.handleBind(conn, req)\n\tcase associateCommand:\n\t\treturn h.handleAssociate(conn, req)\n\tdefault:\n\t\tif err := sendReply(conn, commandNotSupported, nil); err != nil {\n\t\t\treturn fmt.Errorf(\"Failed to send reply: %v\", err)\n\t\t}\n\t\treturn fmt.Errorf(\"Unsupported command: %v\", req.Command)\n\t}\n}\n\n// handleConnect is used to handle a connect command\nfunc (h *StandardRequestHandler) handleConnect(conn io.ReadWriter, req *Request) error {\n\tif h.accessPolicy != nil {\n\t\tif req.DestAddr.IP == nil {\n\t\t\taddr, err := net.ResolveIPAddr(\"ip\", req.DestAddr.FQDN)\n\t\t\tif err != nil {\n\t\t\t\t_ = sendReply(conn, ruleFailure, req.DestAddr)\n\t\t\t\treturn fmt.Errorf(\"unable to resolve host to confirm access\")\n\t\t\t}\n\n\t\t\treq.DestAddr.IP = addr.IP\n\t\t}\n\t\tif allowed, rule := h.accessPolicy.Allowed(req.DestAddr.IP, req.DestAddr.Port); !allowed {","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/socks/request_handler.go#L27-L63","documentation":"In StandardRequestHandler.Handle, when the request's command byte is not connect, bind, or associate, the handler replies with commandNotSupported before failing. This error means writing that reply back to the client also failed, so the underlying send error (broken pipe, reset, closed socket) is reported instead of the command error.","triggerScenarios":"Handle receiving a command byte outside {0x01 connect, 0x02 bind, 0x03 associate} AND sendReply(conn, commandNotSupported, nil) failing to write — e.g. the client already disconnected mid-handshake.","commonSituations":"Aggressive clients closing the connection immediately after sending the request; network drop between greeting and reply; a client using SOCKS extensions/UDP that this handler doesn't recognize.","solutions":["Configure the client to use a supported command (CONNECT=1, BIND=2, UDP ASSOCIATE=3)","Treat the wrapped error as a transport failure: check err.Error() for connection reset/broken pipe and retry with a fresh connection","Update client SOCKS implementation if it sends non-standard command codes","Wrap Serve in retry logic that tolerates races where the client times out and closes first"],"exampleFix":"// server side: tolerate client disconnect before reply\nif err := h.Serve(conn); err != nil {\n    log.Warn().Err(err).Msg(\"socks handshake aborted by client\")\n}","handlingStrategy":"retry","validationCode":"// ensure the command byte is supported before connecting\nif cmd := 0x01; cmd != 0x01 && cmd != 0x02 && cmd != 0x03 {\n    return fmt.Errorf(\"command %d unsupported by server\", cmd)\n}","typeGuard":"func isSupportedCommand(b byte) bool { return b >= 0x01 && b <= 0x03 }","tryCatchPattern":"if err := serve(conn); err != nil {\n    if ne, ok := err.(*net.OpError); ok || strings.Contains(err.Error(), \"reset\") {\n        time.Sleep(backoff); retry(conn)\n    }\n}","preventionTips":["Use only CONNECT (0x01) unless you know BIND/UDP ASSOCIATE are enabled","Set generous client timeouts so the client doesn't hang up before the reply","Retry idempotent requests on a fresh connection"],"tags":["network","socks5","reply-write-failed"],"backgroundTag":"broken-pipe","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}