{"record":{"id":"ddeee48292e2e7af","repo":"AlexxIT/go2rtc","slug":"mjpeg-no-receivers","errorCode":null,"errorMessage":"mjpeg: no receivers","messagePattern":"mjpeg: no receivers","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/mpjpeg/producer.go","lineNumber":42,"sourceCode":"\t\t\t\t{\n\t\t\t\t\tKind:      core.KindVideo,\n\t\t\t\t\tDirection: core.DirectionRecvonly,\n\t\t\t\t\tCodecs: []*core.Codec{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName:        core.CodecJPEG,\n\t\t\t\t\t\t\tClockRate:   90000,\n\t\t\t\t\t\t\tPayloadType: core.PayloadTypeRAW,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}, nil\n}\n\nfunc (c *Producer) Start() error {\n\tif len(c.Receivers) != 1 {\n\t\treturn errors.New(\"mjpeg: no receivers\")\n\t}\n\n\trd := bufio.NewReader(c.Transport.(io.Reader))\n\n\tmjpeg := c.Receivers[0]\n\n\tfor {\n\t\t_, body, err := Next(rd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tc.Recv += len(body)\n\n\t\tif mjpeg != nil {\n\t\t\tpacket := &rtp.Packet{\n\t\t\t\tHeader:  rtp.Header{Timestamp: core.Now90000()},\n\t\t\t\tPayload: body,","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/mpjpeg/producer.go#L24-L60","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nproducer, _ := mpjpeg.NewProducer(transport)\nproducer.Start()\n// after\nproducer, _ := mpjpeg.NewProducer(transport)\nproducer.AddConsumer(mjpegConsumer)\nproducer.Start()","handlingStrategy":"validation","validationCode":"if producer == nil || len(producer.Receivers) != 1 {\n    return errors.New(\"producer requires exactly one receiver before Start\")\n}","typeGuard":"func startable(p *mpjpeg.Producer) bool {\n    return p != nil && len(p.Receivers) == 1\n}","tryCatchPattern":"if err := producer.Start(); err != nil {\n    if strings.Contains(err.Error(), \"no receivers\") {\n        // re-attach consumer and retry once\n        producer.Receivers = []interface{}{consumer}\n        return producer.Start()\n    }\n    return err\n}","preventionTips":["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"],"tags":["mjpeg","producer","pipeline-wiring"],"backgroundTag":"invalid-state-transition","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}