{"record":{"id":"3fafc6fae85828de","repo":"fatedier/frp","slug":"unsupported-wire-protocol-q","errorCode":null,"errorMessage":"unsupported wire protocol %q","messagePattern":"unsupported wire protocol %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/msg/udp_binary.go","lineNumber":336,"sourceCode":"// the framing or codecs used by non-UDP messages on the work connection.\nfunc NewUDPPacketReadWriter(rw io.ReadWriter, wireProtocol, udpPacketCodec string) (ReadWriter, error) {\n\tswitch wireProtocol {\n\tcase \"\", wire.ProtocolV1:\n\t\tif udpPacketCodec != \"\" {\n\t\t\treturn nil, fmt.Errorf(\"UDP packet codec %q requires wire protocol v2\", udpPacketCodec)\n\t\t}\n\t\treturn NewV1ReadWriter(rw), nil\n\tcase wire.ProtocolV2:\n\t\tswitch udpPacketCodec {\n\t\tcase \"\":\n\t\t\treturn NewV2ReadWriter(rw), nil\n\t\tcase wire.UDPPacketCodecBinary:\n\t\t\treturn NewV2BinaryUDPPacketReadWriter(rw), nil\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"unsupported UDP packet codec %q\", udpPacketCodec)\n\t\t}\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unsupported wire protocol %q\", wireProtocol)\n\t}\n}\n","sourceCodeStart":318,"sourceCodeEnd":339,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/msg/udp_binary.go#L318-L339","documentation":"NewUDPPacketReadWriter rejects a wireProtocol string other than \"\", \"v1\", or \"v2\". The factory is the single entry point for choosing the connection codec pair, and an unknown protocol value cannot be mapped to any ReadWriter, so it fails before any I/O. This is nearly always a config or constant mismatch.","triggerScenarios":"Calling NewUDPPacketReadWriter(rw, \"v3\", codec) or a typo like \"V2\" (case-sensitive) or \"websocket\" — the latter being a transport setting, not a wire protocol.","commonSituations":"Confusing transport (kcp/websocket/quic) with wire protocol (v1/v2); hand-built config strings; constants from a different frp version; case-sensitive copy-paste errors.","solutions":["Pass wire.ProtocolV1 or wire.ProtocolV2 (or \"\") — the constants, not hand-typed strings.","Do not put transport names (kcp, qucp, websocket, quic) into the wire protocol field.","Verify the value's case and whitespace if it comes from config parsing."],"exampleFix":"// before\nrw, err := msg.NewUDPPacketReadWriter(conn, \"websocket\", \"\")\n\n// after\nrw, err := msg.NewUDPPacketReadWriter(conn, wire.ProtocolV2, \"\")","handlingStrategy":"validation","validationCode":"switch wireProtocol {\ncase \"\", wire.ProtocolV1, wire.ProtocolV2:\ndefault:\n\treturn fmt.Errorf(\"unsupported wire protocol %q\", wireProtocol)\n}","typeGuard":"func isSupportedWireProtocol(p string) bool {\n\treturn p == \"\" || p == wire.ProtocolV1 || p == wire.ProtocolV2\n}","tryCatchPattern":null,"preventionTips":["Pass wire.ProtocolV1/wire.ProtocolV2 constants, never user-typed strings.","Keep transport settings (kcp/quic/websocket) out of the wire protocol field.","Trim and case-check values parsed from external config."],"tags":["config","validation","protocol","frp"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}