{"record":{"id":"e775a359e05a56bf","repo":"XTLS/Xray-core","slug":"failed-to-read-request","errorCode":null,"errorMessage":"failed to read request","messagePattern":"failed to read request","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/socks/protocol.go","lineNumber":157,"sourceCode":"\n\treturn \"\", nil\n}\n\nfunc (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer net.Conn) (*protocol.RequestHeader, *TempUDPConn, error) {\n\tvar (\n\t\tusername string\n\t\terr      error\n\t)\n\tif username, err = s.auth5(nMethod, reader, writer); err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tvar cmd byte\n\t{\n\t\tbuffer := buf.StackNew()\n\t\tif _, err := buffer.ReadFullFrom(reader, 3); err != nil {\n\t\t\tbuffer.Release()\n\t\t\treturn nil, nil, errors.New(\"failed to read request\").Base(err)\n\t\t}\n\t\tcmd = buffer.Byte(1)\n\t\tbuffer.Release()\n\t}\n\n\trequest := new(protocol.RequestHeader)\n\tif username != \"\" {\n\t\trequest.User = &protocol.MemoryUser{Email: username}\n\t}\n\tswitch cmd {\n\tcase cmdTCPConnect, cmdTorResolve, cmdTorResolvePTR:\n\t\t// We don't have a solution for Tor case now. Simply treat it as connect command.\n\t\trequest.Command = protocol.RequestCommandTCP\n\tcase cmdUDPAssociate:\n\t\tif !s.config.UdpEnabled {\n\t\t\twriteSocks5Response(writer, statusCmdNotSupport, net.AnyIP, net.Port(0))\n\t\t\treturn nil, nil, errors.New(\"UDP is not enabled.\")\n\t\t}","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/socks/protocol.go#L139-L175","documentation":"Thrown in handshake5 (proxy/socks/protocol.go:157) when reading the 3-byte SOCKS5 request header (VER, CMD, RSV) fails after authentication. ReadFullFrom demands exactly 3 bytes; a short read means the client ended, reset, or stalled before sending its request.","triggerScenarios":"Client completes auth negotiation then disconnects (credential-testing tools that only verify auth); malformed clients sending 2 bytes; connection cut by NAT idle timers between auth and request.","commonSituations":"Credential-checker scripts that stop after auth; flaky networks; clients that pipeline incorrectly and desynchronize the stream after a failed auth attempt in a previous connection.","solutions":["Confirm the client sends VER=0x05, CMD, RSV=0x00 immediately after auth completes and reads the auth reply first.","Inspect the base error: EOF = client left on purpose (usually benign); timeout = stalled session.","If using a test tool, use one that performs the full handshake (curl with socks5h is a good reference)."],"exampleFix":"// before: client never reads the auth reply and closes\nwriteAuth(conn); conn.Close()\n\n// after: read reply, then send the CONNECT request\nio.ReadFull(conn, make([]byte, 2)) // 0x01 0x00\nconn.Write([]byte{0x05, 0x01, 0x00, 0x03, 0x0B, 'e','x','a','m','p','l','e','.','c','o','m', 0x00, 0x50})","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to read request\") {\n    logDebug(\"peer disappeared after SOCKS5 auth\")\n    conn.Close()\n}","preventionTips":["Always complete the full SOCKS5 handshake: greeting -> auth -> request.","Validate client implementations with curl --socks5-hostname before deploying."],"tags":["socks","socks5","protocol","truncated-request","network","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}