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

  1. Pass wire.ProtocolV1 or wire.ProtocolV2 (or "") — the constants, not hand-typed strings.
  2. Do not put transport names (kcp, qucp, websocket, quic) into the wire protocol field.
  3. 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

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


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/3fafc6fae85828de. Report an issue: GitHub.