AlexxIT/go2rtc · error
tcp: buffer too small
Error message
tcp: buffer too small
What it means
Read reads a 2-byte big-endian length prefix followed by that many bytes into the caller-supplied buffer p. If len(p) is smaller than the announced frame size, the library refuses to read (leaving the frame unread) and returns "tcp: buffer too small". This is a caller contract error: the destination buffer must be at least as large as the incoming frame.
Solutions
- Pass a buffer at least as large as the maximum frame size (e.g. 1200 bytes, matching the internal loop buffer)
- Read the 2-byte length prefix first and grow the buffer to the announced size before the full read
- Check protocol/firmware version changes that increased maximum frame sizes
- Handle the returned error by draining/resetting the connection — the oversized frame is left in the stream and will corrupt subsequent reads if ignored
Example fix
// before buf := make([]byte, 64) n, err := conn.Read(buf) // after buf := make([]byte, 1200) // >= max cs2 frame size n, err := conn.Read(buf)
Defensive patterns
Strategy: validation
Validate before calling
const maxFrame = 1200
func validateBuf(p []byte) error {
if len(p) < maxFrame { return fmt.Errorf("buffer %d < max frame %d", len(p), maxFrame) }
return nil
}
// call validateBuf(buf) before conn.Read(buf) Type guard
func bufLargeEnough(p []byte) bool { return cap(p) >= 1200 } Try / catch
if err := validateBuf(buf); err != nil { buf = make([]byte, 1200) }
n, err := conn.Read(buf)
if err != nil && strings.Contains(err.Error(), "buffer too small") {
// stream desynced: reset the connection
conn.Reset()
} Prevention
- Always allocate buffers at the protocol's maximum frame size
- Account for header vs payload size when sizing buffers
- Re-check buffer sizes after any firmware/protocol upgrade
- Treat this error as fatal for the stream and reset the connection
When it happens
Trigger: Calling Read with a buffer shorter than the frame the peer sent — e.g. a fixed small scratch buffer receiving a larger frame, or a mis-sized buffer after a protocol/firmware change that increased maximum frame size.
Common situations: Hard-coded buffer sizes that assume a max frame which the firmware version exceeds; reusing a small tmp buffer for a new message type; off-by-N when accounting for the header vs payload size.
Related errors
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/2be1b10315146455.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/xiaomi/miss/cs2/conn.go:392
if err != nil {
return nil, err
}
return &tcpConn{conn.(*net.TCPConn), bufio.NewReader(conn)}, nil
}
type tcpConn struct {
*net.TCPConn
rd *bufio.Reader
}
func (c *tcpConn) Read(p []byte) (n int, err error) {
tmp := make([]byte, 8)
if _, err = io.ReadFull(c.rd, tmp); err != nil {
return
}
n = int(binary.BigEndian.Uint16(tmp))
if len(p) < n {
return 0, fmt.Errorf("tcp: buffer too small")
}
_, err = io.ReadFull(c.rd, p[:n])
//log.Printf("<- %x%x", tmp, p[:n])
return
}
func (c *tcpConn) Write(req []byte) (n int, err error) {
n = len(req)
buf := make([]byte, 8+n)
binary.BigEndian.PutUint16(buf, uint16(n))
buf[2] = magicTCP
copy(buf[8:], req)
//log.Printf("-> %x", buf)
_, err = c.TCPConn.Write(buf)
return
}
func newDataChannel(pushSize, popSize int) *dataChannel {View on GitHub (pinned to c245815e75)