AlexxIT/go2rtc · error
mjpeg: no receivers
Error message
mjpeg: no receivers
What it means
An MJPEG Producer must have exactly one receiver (codec consumer) attached before Start is called; it reads the multipart stream from the transport and pushes frames into that single receiver. If Receivers is empty or has more than one entry, the producer cannot route frames and refuses to start.
Solutions
- Attach exactly one MJPEG consumer/receiver to the producer before calling Start.
- Check pipeline ordering: create the consumer first, then the producer, then start.
- Inspect why receivers were removed — a previously-attached consumer that errored out may have deregistered itself; fix the consumer's error first.
- Log len(producer.Receivers) just before Start to confirm the wiring.
Example fix
// before producer, _ := mpjpeg.NewProducer(transport) producer.Start() // after producer, _ := mpjpeg.NewProducer(transport) producer.AddConsumer(mjpegConsumer) producer.Start()
Defensive patterns
Strategy: validation
Validate before calling
if producer == nil || len(producer.Receivers) != 1 {
return errors.New("producer requires exactly one receiver before Start")
} Type guard
func startable(p *mpjpeg.Producer) bool {
return p != nil && len(p.Receivers) == 1
} Try / catch
if err := producer.Start(); err != nil {
if strings.Contains(err.Error(), "no receivers") {
// re-attach consumer and retry once
producer.Receivers = []interface{}{consumer}
return producer.Start()
}
return err
} Prevention
- Always attach the consumer before calling Start, never after
- Follow the standard go2rtc pipeline API instead of constructing producers manually
- Check consumer lifecycle: an exited consumer removes its receiver, leaving zero
- Assert len(Receivers) == 1 in tests covering producer startup
When it happens
Trigger: Calling Producer.Start() when c.Receivers has a length other than 1 — i.e. the producer was built without an attached consumer, or with multiple consumers.
Common situations: Custom pipeline code that forgot to wire a receiver before starting the producer; a consumer that already exited and removed itself, leaving zero receivers; framework misuse building the producer manually instead of through the standard consumer API.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/ddeee48292e2e7af.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/mpjpeg/producer.go:42
{
Kind: core.KindVideo,
Direction: core.DirectionRecvonly,
Codecs: []*core.Codec{
{
Name: core.CodecJPEG,
ClockRate: 90000,
PayloadType: core.PayloadTypeRAW,
},
},
},
},
},
}, nil
}
func (c *Producer) Start() error {
if len(c.Receivers) != 1 {
return errors.New("mjpeg: no receivers")
}
rd := bufio.NewReader(c.Transport.(io.Reader))
mjpeg := c.Receivers[0]
for {
_, body, err := Next(rd)
if err != nil {
return err
}
c.Recv += len(body)
if mjpeg != nil {
packet := &rtp.Packet{
Header: rtp.Header{Timestamp: core.Now90000()},
Payload: body,View on GitHub (pinned to c245815e75)