{"record":{"id":"7f0ff93c115e56b6","repo":"AlexxIT/go2rtc","slug":"rtsp-wrong-mode-for-gettrack","errorCode":null,"errorMessage":"rtsp: wrong mode for GetTrack","messagePattern":"rtsp: wrong mode for GetTrack","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/rtsp/producer.go","lineNumber":43,"sourceCode":"\tcase core.ModeActiveProducer:\n\t\tif c.state == StatePlay {\n\t\t\tif err := c.Reconnect(); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\n\t\tvar err error\n\t\tchannel, err = c.SetupMedia(media)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tc.state = StateSetup\n\tcase core.ModePassiveConsumer:\n\t\t// Backchannel\n\t\tchannel = byte(len(c.Senders)) * 2\n\tdefault:\n\t\treturn nil, errors.New(\"rtsp: wrong mode for GetTrack\")\n\t}\n\n\ttrack := core.NewReceiver(media, codec)\n\ttrack.ID = channel\n\tc.Receivers = append(c.Receivers, track)\n\n\treturn track, nil\n}\n\nfunc (c *Conn) Start() (err error) {\n\tcore.Assert(c.mode == core.ModeActiveProducer || c.mode == core.ModePassiveProducer)\n\n\tfor {\n\t\tok := false\n\n\t\tc.stateMu.Lock()\n\t\tswitch c.state {\n\t\tcase StateNone:","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/rtsp/producer.go#L25-L61","documentation":"GetTrack on an RTSP producer Conn only supports two modes: ModeActiveProducer (client fetches media via SETUP/PLAY) and ModePassiveConsumer (backchannel receiver). If the connection was created in any other mode (e.g. ModePassiveProducer or ModeActiveConsumer), the mode's consumers use Senders, not Receivers, so requesting a receive track is an invalid operation and this error is returned.","triggerScenarios":"Calling GetTrack(media, codec) on a Conn whose c.mode is neither core.ModeActiveProducer nor core.ModePassiveConsumer — for example calling GetTrack on a connection built as a passive producer (server-side publishing) or active consumer, where pulling incoming media is not applicable.","commonSituations":"Mixing up consumer/producer APIs: using a producer-side Conn (one publishing to go2rtc, e.g. from an RTSP server session) and then trying to read tracks from it; creating the Conn with the wrong core.Mode; refactoring code that reused a consumer Conn as a producer.","solutions":["Only call GetTrack on Conns operating as ModeActiveProducer or ModePassiveConsumer; check c.mode before calling.","If you need to send media, use the Senders/GetTrack-for-sending API appropriate to the mode instead.","Fix how the Conn is created so it uses the intended mode (ModeActiveProducer for pulling an RTSP stream)."],"exampleFix":"// before\ntrack, err := conn.GetTrack(media, codec) // conn.mode == ModePassiveProducer\n// after\nif conn.Mode == core.ModeActiveProducer || conn.Mode == core.ModePassiveConsumer {\n    track, err := conn.GetTrack(media, codec)\n}","handlingStrategy":"validation","validationCode":"func canGetTrack(mode core.Mode) bool {\n    return mode == core.ModeActiveProducer || mode == core.ModePassiveConsumer\n}\nif !canGetTrack(conn.Mode) {\n    return errors.New(\"GetTrack not supported for this connection mode\")\n}","typeGuard":"func isReceiverMode(mode core.Mode) bool {\n    return mode == core.ModeActiveProducer || mode == core.ModePassiveConsumer\n}","tryCatchPattern":"track, err := conn.GetTrack(media, codec)\nif err != nil {\n    if strings.Contains(err.Error(), \"wrong mode for GetTrack\") {\n        // fall back to the sending-side API for this mode\n    }\n}","preventionTips":["Know the Conn role (pull vs publish) before touching tracks.","Expose c.mode via a getter and branch consumer/producer logic on it.","Add unit tests covering each core.Mode against the track APIs."],"tags":["rtsp","invalid-state","api-misuse"],"backgroundTag":"unsupported-operation","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}