{"record":{"id":"3872fb8542216e88","repo":"AlexxIT/go2rtc","slug":"ring-msg-string","errorCode":null,"errorMessage":"ring: ${msg.String()}","messagePattern":"ring: \\$\\{msg\\.String\\(\\)\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/ring/client.go","lineNumber":163,"sourceCode":"\t\t\t\t\"mlineindex\": iceCandidate.SDPMLineIndex,\n\t\t\t}\n\n\t\t\tif err = client.wsClient.sendSessionMessage(\"ice\", icePayload); err != nil {\n\t\t\t\tclient.connected.Done(err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\tcase pion.PeerConnectionState:\n\t\t\tswitch msg {\n\t\t\tcase pion.PeerConnectionStateNew:\n\t\t\t\tbreak\n\t\t\tcase pion.PeerConnectionStateConnecting:\n\t\t\t\tbreak\n\t\t\tcase pion.PeerConnectionStateConnected:\n\t\t\t\tclient.connected.Done(nil)\n\t\t\tdefault:\n\t\t\t\tclient.Stop()\n\t\t\t\tclient.connected.Done(errors.New(\"ring: \" + msg.String()))\n\t\t\t}\n\t\t}\n\t})\n\n\tclient.prod = prod\n\n\t// Setup media configuration\n\tmedias := []*core.Media{\n\t\t{\n\t\t\tKind:      core.KindAudio,\n\t\t\tDirection: core.DirectionSendRecv,\n\t\t\tCodecs: []*core.Codec{\n\t\t\t\t{\n\t\t\t\t\tName:      \"opus\",\n\t\t\t\t\tClockRate: 48000,\n\t\t\t\t\tChannels:  2,\n\t\t\t\t},\n\t\t\t},","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/ring/client.go#L145-L181","documentation":"The ring client watches WebRTC peer connection state changes; any terminal state other than Connected (e.g. Failed, Closed, Disconnected) stops the client and completes the connection with this error containing the pion state string.","triggerScenarios":"The pion PeerConnection transitions to a failed/closed/disconnected state during setup — ICE negotiation failure, no network path to the camera, or the peer connection being closed prematurely.","commonSituations":"Camera unreachable through NAT/firewall (ICE failure); Ring server rejecting the SDP offer; attempting to reuse a client after Stop was called.","solutions":["Read the state suffix in the message (e.g. \"ring: failed\") to identify the WebRTC failure","Ensure ICE/STUN connectivity to the Ring camera network","Refresh credentials and retry the dial","Avoid calling Stop before the connection completes"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// no pre-call validation possible; ensure network allows UDP/STUN for WebRTC\nif !udpConnectivityOK(stunServer) {\n    return errors.New(\"WebRTC connectivity required for ring streams\")\n}","typeGuard":null,"tryCatchPattern":"client, err := Dial(ctx, query)\nif err != nil && strings.HasPrefix(err.Error(), \"ring: \") {\n    state := strings.TrimPrefix(err.Error(), \"ring: \")\n    log.Printf(\"peer connection ended in state %s, retrying\", state)\n    client, err = Dial(ctx, query)\n}","preventionTips":["Verify ICE/STUN/TURN connectivity in the deployment environment","Don't reuse clients after Stop; create a fresh client per session","Parse the pion state out of the message to branch on failure type"],"tags":["webrtc","peer-connection","pion"],"backgroundTag":"webrtc-connection-failed","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"}