AlexxIT/go2rtc · error

read error

Error message

read error

What it means

dvrip.Client.ReadChunk (pkg/dvrip/client.go:161) reads the DVRIP binary chunk framing: a 20-byte header whose first byte must be 0xFF. If b[0] != 255 the stream is not a valid DVRIP chunk and the client returns "read error". Like other start-byte checks, it means the TCP stream is misaligned or is not speaking DVRIP at all.

Solutions

  1. Reconnect: close the client and Dial again; the stream framing is unrecoverable once desynced.
  2. Verify the target port speaks DVRIP (typically 34567) and not the camera's HTTP interface.
  3. Check device model/firmware compatibility with this DVRIP driver.
  4. Inspect raw traffic with tcpdump/wireshark to see what bytes actually arrive at that offset.
  5. Rule out middleboxes (transparent proxies, DPI) altering the TCP payload.

Example fix

// before: retrying reads on a desynced connection
pkt, err := client.ReadPacket() // read error every time
// after
if err != nil {
    client.Close()
    client, err = dvrip.Dial(ctx, host, user, pass) // fresh session
}
Defensive patterns

Strategy: fallback

Validate before calling

// sanity-check the port speaks DVRIP before Dial
conn, err := net.DialTimeout("tcp", host+":34567", time.Second)
if err != nil { return err }
conn.Close()

Try / catch

pkt, err := client.ReadPacket()
if err != nil && err.Error() == "read error" {
    client.Close()
    client, err = dvripReconnect(ctx) // desynced stream; reconnect
}

Prevention

When it happens

Trigger: ReadChunk, invoked by ReadPacket and ReadJSON, when the first header byte is not 0xFF — e.g. garbage after a session drop, an HTTP error page, or a device answering with a different protocol on that port.

Common situations: Connecting to the wrong port (web UI port vs DVRIP port 34567); camera/firmware closing or corrupting the connection mid-read; firewall/NAT injecting data; stale session where the device reset the stream.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at pkg/dvrip/client.go:161

	if err = c.conn.SetWriteDeadline(time.Now().Add(time.Second * 5)); err != nil {
		return 0, err
	}

	return c.conn.Write(b)
}

func (c *Client) ReadChunk() (b []byte, err error) {
	if err = c.conn.SetReadDeadline(time.Now().Add(time.Second * 5)); err != nil {
		return
	}

	b = make([]byte, 20)
	if _, err = io.ReadFull(c.rd, b); err != nil {
		return
	}

	if b[0] != 255 {
		return nil, errors.New("read error")
	}

	c.session = binary.LittleEndian.Uint32(b[4:])
	size := binary.LittleEndian.Uint32(b[16:])

	b = make([]byte, size)
	if _, err = io.ReadFull(c.rd, b); err != nil {
		return
	}

	return
}

func (c *Client) ReadPacket() (pType byte, payload []byte, err error) {
	var b []byte

	// many cameras may split packet to multiple chunks
	// some rare cameras may put multiple packets to single chunk

View on GitHub (pinned to c245815e75)