AlexxIT/go2rtc · error

unsupported frame type

Error message

unsupported frame type: %d

What it means

The websocket client reader only accepts binary frames (opcode 0x2). Any other frame type — text (0x1), ping (0x9), pong (0xA), close (0x8), or continuation (0x0) — results in this error and aborts the read. The library is intentionally minimal and assumes the peer sends binary-only messages.

Solutions

  1. Ensure the peer sends binary frames (send Blob/ArrayBuffer in JS; TextMessage→BinaryMessage in Go clients).
  2. If the peer must send text, change this client to also accept TextMessage in the switch (rebuild the library).
  3. Handle control frames (ping/close) by responding before data frames reach this reader, or strip them with an intermediary.
  4. If the server speaks JSON, marshal your structs to bytes and send as binary on both ends.

Example fix

// before
switch frameType {
case BinaryMessage:
default:
	return 0, fmt.Errorf("unsupported frame type: %d", frameType)
}
// after
switch frameType {
case BinaryMessage, TextMessage:
case PingMessage:
	writePong(w.conn)
	return 0, nil
default:
	return 0, fmt.Errorf("unsupported frame type: %d", frameType)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Negotiate binary-only subprotocol or verify peer frame usage before streaming
if !peerSupportsBinaryFrames(serverURL) {
	return errors.New("peer sends non-binary frames; unsupported by client")
}

Type guard

func isBinaryOpcode(b byte) bool { return b&0xF == 0x2 }

Try / catch

n, err := wsConn.Read(buf)
if err != nil {
	var frameErr unsupportedFrameError
	if errors.As(err, &frameErr) {
		return handleNonBinaryFrame(frameErr.FrameType)
	}
	return err
}

Prevention

When it happens

Trigger: Calling Read on a websocket.Conn when the remote peer sends a text frame, or when a ping/pong/close control frame arrives mid-stream; the frame type is computed as byte&0xF and anything other than BinaryMessage errors.

Common situations: Talking to a server that defaults to JSON text frames; proxies/intermediaries injecting ping frames; misconfigured client that upgrades with a text-oriented subprotocol; library version mismatch where the peer protocol changed.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/6beb5594f9d661eb. Report an issue: GitHub.

Appendix: source

Thrown at pkg/tcp/websocket/client.go:39

}

const finalBit = 0x80
const maskBit = 0x80

func (w *Client) Read(b []byte) (n int, err error) {
	if w.remain == 0 {
		b2 := make([]byte, 2)
		if _, err = io.ReadFull(w.conn, b2); err != nil {
			return 0, err
		}

		frameType := b2[0] & 0xF
		w.remain = int(b2[1] & 0x7F)

		switch frameType {
		case BinaryMessage:
		default:
			return 0, fmt.Errorf("unsupported frame type: %d", frameType)
		}

		switch w.remain {
		case 126:
			if _, err = io.ReadFull(w.conn, b2); err != nil {
				return 0, err
			}
			w.remain = int(binary.BigEndian.Uint16(b2))
		case 127:
			b8 := make([]byte, 8)
			if _, err = io.ReadFull(w.conn, b8); err != nil {
				return 0, err
			}
			w.remain = int(binary.BigEndian.Uint64(b8))
		}
	}

	if w.remain > len(b) {

View on GitHub (pinned to c245815e75)