fatedier/frp · error
unsupported wire protocol %q
Error message
unsupported wire protocol %q
What it means
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.
Source
Thrown at pkg/msg/udp_binary.go:336
// the framing or codecs used by non-UDP messages on the work connection.
func NewUDPPacketReadWriter(rw io.ReadWriter, wireProtocol, udpPacketCodec string) (ReadWriter, error) {
switch wireProtocol {
case "", wire.ProtocolV1:
if udpPacketCodec != "" {
return nil, fmt.Errorf("UDP packet codec %q requires wire protocol v2", udpPacketCodec)
}
return NewV1ReadWriter(rw), nil
case wire.ProtocolV2:
switch udpPacketCodec {
case "":
return NewV2ReadWriter(rw), nil
case wire.UDPPacketCodecBinary:
return NewV2BinaryUDPPacketReadWriter(rw), nil
default:
return nil, fmt.Errorf("unsupported UDP packet codec %q", udpPacketCodec)
}
default:
return nil, fmt.Errorf("unsupported wire protocol %q", wireProtocol)
}
}
View on GitHub (pinned to 6c8a8d0a97)
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.
Example fix
// before rw, err := msg.NewUDPPacketReadWriter(conn, "websocket", "") // after rw, err := msg.NewUDPPacketReadWriter(conn, wire.ProtocolV2, "")
Defensive patterns
Strategy: validation
Validate before calling
switch wireProtocol {
case "", wire.ProtocolV1, wire.ProtocolV2:
default:
return fmt.Errorf("unsupported wire protocol %q", wireProtocol)
} Type guard
func isSupportedWireProtocol(p string) bool {
return p == "" || p == wire.ProtocolV1 || p == wire.ProtocolV2
} Prevention
- 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.
When it happens
Trigger: Calling NewUDPPacketReadWriter(rw, "v3", codec) or a typo like "V2" (case-sensitive) or "websocket" — the latter being a transport setting, not a wire protocol.
Common situations: 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.
Related errors
- exec configuration is required when type is 'exec'
- file path cannot be empty
- exec command cannot be empty
- exec env name cannot be empty
- exec env name cannot contain '='
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/3fafc6fae85828de.
Report an issue: GitHub.