{"record":{"id":"4f1a98f74dbb0ed8","repo":"AlexxIT/go2rtc","slug":"connection-is-nil","errorCode":null,"errorMessage":"connection is nil","messagePattern":"connection is nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wyze/client.go","lineNumber":206,"sourceCode":"\t_, err := c.conn.WriteAndWaitIOCtrl(k10056, c.matchHL(KCmdSetResolutionResp), 5*time.Second)\n\treturn err\n}\n\nfunc (c *Client) StartVideo() error {\n\tk10010 := c.buildK10010(MediaTypeVideo, true)\n\t_, err := c.conn.WriteAndWaitIOCtrl(k10010, c.matchHL(KCmdControlChannelResp), 5*time.Second)\n\treturn err\n}\n\nfunc (c *Client) StartAudio() error {\n\tk10010 := c.buildK10010(MediaTypeAudio, true)\n\t_, err := c.conn.WriteAndWaitIOCtrl(k10010, c.matchHL(KCmdControlChannelResp), 5*time.Second)\n\treturn err\n}\n\nfunc (c *Client) StartIntercom() error {\n\tif c.conn == nil {\n\t\treturn fmt.Errorf(\"connection is nil\")\n\t}\n\n\tif c.conn.IsBackchannelReady() {\n\t\treturn nil\n\t}\n\n\tk10010 := c.buildK10010(MediaTypeReturnAudio, true)\n\tif _, err := c.conn.WriteAndWaitIOCtrl(k10010, c.matchHL(KCmdControlChannelResp), 5*time.Second); err != nil {\n\t\treturn fmt.Errorf(\"enable return audio: %w\", err)\n\t}\n\n\tif c.verbose {\n\t\tfmt.Printf(\"[Wyze] Speaker channel enabled, waiting for readiness...\\n\")\n\t}\n\n\treturn c.conn.AVServStart()\n}\n","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/wyze/client.go#L188-L224","documentation":"StartIntercom enables two-way talk by opening the return-audio (speaker) channel on the Wyze camera. This error is returned when c.conn is nil, meaning Dial() has not completed (or failed) before StartIntercom was called. The library refuses to write control commands on a non-existent connection.","triggerScenarios":"Calling StartIntercom (directly or via AddTrack) before Dial() succeeds, after Dial() returned an error, or on a Client that was constructed but never connected. Also if a previous disconnect set conn to nil.","commonSituations":"Race between WebRTC track negotiation and camera connection; forgot to call Dial() first; Dial() failed silently in a goroutine and the caller proceeded; reconnect logic left the client in a disconnected state.","solutions":["Call client.Dial() and check its error before calling StartIntercom.","Serialize setup so AddTrack/StartIntercom only run after connection is established (sync.Once, channel signal, or callback from Dial).","If reconnecting, re-run Dial and re-check conn != nil before retrying intercom."],"exampleFix":"// before\ngo client.Dial()\nclient.StartIntercom()\n\n// after\nif err := client.Dial(); err != nil {\n    return err\n}\nif err := client.StartIntercom(); err != nil {\n    return err\n}","handlingStrategy":"validation","validationCode":"if client == nil || !client.IsConnected() {\n    return fmt.Errorf(\"wyze client not connected; call Dial first\")\n}\nreturn client.StartIntercom()","typeGuard":"func ready(c *wyze.Client) bool { return c != nil && c.IsConnected() }","tryCatchPattern":null,"preventionTips":["Always pair Dial() with its error check before any other client call","Drive intercom setup from a connection-established callback, not a goroutine race","Re-verify connection state after any reconnect"],"tags":["go","connection-state","lifecycle"],"backgroundTag":"connection-refused","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"}