{"record":{"id":"8e803b92f2198381","repo":"fatedier/frp","slug":"unexpected-frame-type-d-want-d","errorCode":null,"errorMessage":"unexpected frame type %d, want %d","messagePattern":"unexpected frame type (.+?), want (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"client/control_session.go","lineNumber":184,"sourceCode":"\t}\n\tif err := rw.WriteMsg(loginMsg); err != nil {\n\t\treturn nil, err\n\t}\n\n\t_ = conn.SetReadDeadline(time.Now().Add(10 * time.Second))\n\tdefer func() {\n\t\t_ = conn.SetReadDeadline(time.Time{})\n\t}()\n\n\tvar cryptoContext *wire.CryptoContext\n\tvar udpPacketCodec string\n\tif wireConn != nil {\n\t\tserverHelloFrame, err := wireConn.ReadFrame()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif serverHelloFrame.Type != wire.FrameTypeServerHello {\n\t\t\treturn nil, fmt.Errorf(\"unexpected frame type %d, want %d\", serverHelloFrame.Type, wire.FrameTypeServerHello)\n\t\t}\n\t\tvar serverHello wire.ServerHello\n\t\tif err := wireConn.UnmarshalFrame(serverHelloFrame, &serverHello); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif serverHello.Error != \"\" {\n\t\t\treturn nil, errors.New(serverHello.Error)\n\t\t}\n\t\tcryptoContext, err = wire.NewClientCryptoContext(clientHelloPayload, serverHelloFrame.Payload)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tudpPacketCodec = serverHello.Selected.Message.UDPPacketCodec\n\t}\n\n\tvar loginRespMsg msg.LoginResp\n\tif err := rw.ReadMsgInto(&loginRespMsg); err != nil {\n\t\treturn nil, err","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/client/control_session.go#L166-L202","documentation":"During the wire-protocol login handshake, the first frame frpc reads from the connection must be a FrameTypeServerHello. Any other frame type (or bytes that decode to a different type) fails here. It means the peer on the other end of the connection is not speaking the expected frps wire handshake as the very first message.","triggerScenarios":"Connecting to a port served by something other than a compatible frps: an older frps without the hello-first handshake, an HTTP server, or a general TCP service; or a proxy in front returning its own protocol bytes first. Only on the path where wireConn is non-nil (modern wire protocol).","commonSituations":"Wrong serverAddr/serverPort pointing at an frps bind port vs dashboard port, or an entirely unrelated service; frpc much newer than frps (or vice versa) with handshake-order changes; connecting through a forward proxy that sends a greeting first.","solutions":["Verify serverAddr/serverPort point to the frps bind port (bindPort), not the webServer/dashboard port","Upgrade frpc and frps to the same version so both sides speak the same handshake","Remove intermediary proxies/LBs that inject their own protocol bytes on that connection","Test connectivity directly: nc <server> <port> should not immediately return HTTP text"],"exampleFix":"# frpc.toml — before\nserverAddr = \"example.com\"\nserverPort = 7500 # dashboard port, wrong\n\n# after\nserverAddr = \"example.com\"\nserverPort = 7000 # frps bindPort","handlingStrategy":"validation","validationCode":"func portSpeaksFrp(addr string, timeout time.Duration) bool {\n\tconn, err := net.DialTimeout(\"tcp\", addr, timeout)\n\tif err != nil {\n\t\treturn false\n\t}\n\tdefer conn.Close()\n\t_ = conn.SetReadDeadline(time.Now().Add(2 * time.Second))\n\tbuf := make([]byte, 16)\n\tn, _ := conn.Read(buf)\n\t// an HTTP greeting (e.g. 'HTTP/', 'GET') means wrong port\n\ts := string(buf[:n])\n\treturn !strings.HasPrefix(s, \"HTTP/\") && !strings.Contains(s, \"GET \")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Point serverPort at frps bindPort, never the dashboard/webServer port","Keep frpc/frps versions matched across upgrades","Prefer direct connectivity over protocol-mangling proxies for the control connection"],"tags":["frp","frpc","handshake","protocol","network"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}