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
- Reconnect: close the client and Dial again; the stream framing is unrecoverable once desynced.
- Verify the target port speaks DVRIP (typically 34567) and not the camera's HTTP interface.
- Check device model/firmware compatibility with this DVRIP driver.
- Inspect raw traffic with tcpdump/wireshark to see what bytes actually arrive at that offset.
- 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
- Connect to the DVRIP port (usually 34567), not the HTTP UI port
- Recreate the client on any protocol error; don't retry reads
- Verify device model/firmware compatibility
- Monitor TCP resets and re-Dial proactively
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
- wrong start byte
- eseecloud: wrong start byte
- dvrip: can't probe medias
- flv: wrong header
- malformed response
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 chunkView on GitHub (pinned to c245815e75)