AlexxIT/go2rtc · warning
pop buffer is full
Error message
pop buffer is full
What it means
Push delivers a completed data frame by sending it on the c.popBuf channel without blocking; when the channel's buffer is full (the consumer isn't draining fast enough) it returns "pop buffer is full" immediately. It is a backpressure signal: frames would otherwise block the worker or be lost, so the library fails fast instead.
Solutions
- Ensure a dedicated consumer goroutine continuously drains the connection's receive channel
- Increase the popBuf channel capacity at connection creation to absorb bursts
- On this error, reconnect or resync sequence numbers — the frame was NOT delivered, so handle retransmission (PushSeq sequencing helps detect gaps)
- Apply backpressure upstream (pause the sender or reduce inflight commands) instead of letting frames queue unboundedly
Example fix
// before
for data := range frames {
slowProcess(data) // blocks; popBuf fills up
}
// after
go func() {
for data := range frames {
go slowProcess(data) // keep draining popBuf promptly
}
}() Defensive patterns
Strategy: fallback
Validate before calling
// drain pending frames before pushing more, or check channel occupancy
if len(popBuf) == cap(popBuf) {
return fmt.Errorf("consumer stalled: pop buffer full")
} Type guard
func consumerHealthy(popBuf chan []byte) bool { return len(popBuf) < cap(popBuf) } Try / catch
if err := conn.Push(frame); err != nil {
if strings.Contains(err.Error(), "pop buffer is full") {
// backpressure: drop/requeue frame and resync via seq numbers
metrics.BackpressureInc()
return requeue(frame)
}
return err
} Prevention
- Run a dedicated goroutine that continuously drains the receive channel
- Size popBuf capacity for the expected burst rate
- Monitor channel occupancy and apply upstream backpressure early
- On frame drop, use PushSeq sequence numbers to detect and recover gaps
When it happens
Trigger: Calling Push (via PushSeq) when the application is not draining popBuf fast enough — typically during bursts of incoming frames while the consumer is blocked, slow, or has exited.
Common situations: Consumer goroutine exited or is stuck in slow processing; burst of frames after a reconnect; popBuf capacity too small for the data rate; forgetting to consume in a fire-and-forget setup.
Related errors
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/f24eafd063c68263.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/xiaomi/miss/cs2/conn.go:448
}
func (c *dataChannel) Push(b []byte) error {
c.waitData = append(c.waitData, b...)
for len(c.waitData) > 4 {
// Every new data starts with size. There can be several data inside one packet.
if c.waitSize == 0 {
c.waitSize = int(binary.BigEndian.Uint32(c.waitData))
c.waitData = c.waitData[4:]
}
if c.waitSize > len(c.waitData) {
break
}
select {
case c.popBuf <- c.waitData[:c.waitSize]:
default:
return fmt.Errorf("pop buffer is full")
}
c.waitData = c.waitData[c.waitSize:]
c.waitSize = 0
}
return nil
}
func (c *dataChannel) Pop() ([]byte, bool) {
data, ok := <-c.popBuf
return data, ok
}
func (c *dataChannel) Close() {
close(c.popBuf)
}
// PushSeq returns how many seq were processed.View on GitHub (pinned to c245815e75)