{"record":{"id":"4756ffbb7e88f135","repo":"fatedier/frp","slug":"unknown-v2-message-type-d","errorCode":null,"errorMessage":"unknown v2 message type %d","messagePattern":"unknown v2 message type (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/msg/wire_v2.go","lineNumber":133,"sourceCode":"func (rw *V2ReadWriter) WriteMsg(m Message) error {\n\tf, err := EncodeV2MessageFrame(m)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn rw.conn.WriteFrame(f)\n}\n\nfunc DecodeV2MessageFrame(f *wire.Frame) (Message, error) {\n\tif f.Type != wire.FrameTypeMessage {\n\t\treturn nil, fmt.Errorf(\"unexpected frame type %d, want %d\", f.Type, wire.FrameTypeMessage)\n\t}\n\tif len(f.Payload) < 2 {\n\t\treturn nil, fmt.Errorf(\"message frame payload too short\")\n\t}\n\ttypeID := binary.BigEndian.Uint16(f.Payload[:2])\n\tt, ok := v2MsgReflectTypeMap[typeID]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"unknown v2 message type %d\", typeID)\n\t}\n\tm := reflect.New(t).Interface()\n\tif err := json.Unmarshal(f.Payload[2:], m); err != nil {\n\t\treturn nil, err\n\t}\n\treturn m, nil\n}\n\nfunc DecodeV2MessageFrameInto(f *wire.Frame, out Message) error {\n\tif f.Type != wire.FrameTypeMessage {\n\t\treturn fmt.Errorf(\"unexpected frame type %d, want %d\", f.Type, wire.FrameTypeMessage)\n\t}\n\tif len(f.Payload) < 2 {\n\t\treturn fmt.Errorf(\"message frame payload too short\")\n\t}\n\n\ttypeID := binary.BigEndian.Uint16(f.Payload[:2])\n\toutType := reflect.TypeOf(out)","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/msg/wire_v2.go#L115-L151","documentation":"DecodeV2MessageFrame looked up the 2-byte type ID in v2MsgReflectTypeMap (built from the 18 registered message types, IDs 1-18 plus 19 for binary UDP) and found no entry. The peer sent a type ID this build does not know — either a message kind introduced in a newer frp version, a removed legacy ID, or garbage bytes. Because the JSON body layout is type-specific, decoding cannot proceed.","triggerScenarios":"A newer frps sends a message type not present in the older frpc's registry (forward-compat gap); a peer from a different protocol entirely; fuzzed type IDs; desynchronized stream landing on this decoder.","commonSituations":"Version skew between frpc and frps after upgrading only one side; custom forks that add message types without coordinating IDs; connecting a non-frp service to an frp port.","solutions":["Upgrade both frpc and frps to the same frp release.","If you fork the protocol, allocate new type IDs consistently on both sides and rebuild both binaries.","Treat the error as fatal for the connection — the following JSON body cannot be interpreted.","Verify you are connecting to an actual frp v2 endpoint, not some other service on that port."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"m, err := msg.DecodeV2MessageFrame(f)\nif err != nil {\n\tif strings.Contains(err.Error(), \"unknown v2 message type\") {\n\t\t// peer speaks a newer/older protocol: version skew — upgrade both sides, then reconnect\n\t\tconn.Close()\n\t\treturn err\n\t}\n}","preventionTips":["Run the same frp release on frpc and frps; pin versions in deployment tooling.","If forking the protocol, keep a shared type-ID registry and version handshake.","Treat unknown-type errors as fatal; the body layout is unknowable."],"tags":["protocol","version-mismatch","frp","message-registry"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}