AlexxIT/go2rtc · error

webrtc:

Error message

webrtc: 

What it means

During the WebRTC connection state change, the peer connection entered a state other than Connecting/Connected (failed, disconnected, closed, etc.). go2rtc signals completion with an error carrying pion's state string.

Solutions

  1. Check that ICE servers (STUN/TURN) are configured and reachable from both ends
  2. Verify UDP ports/firewall allow WebRTC traffic, or route through TURN
  3. Confirm the WHEP/signaling server session is still valid (token expiry)
  4. Read the appended state string (e.g. "webrtc: failed") to identify the exact pion state
Defensive patterns

Strategy: retry

Try / catch

prod, err := webrtcClient(url)
if err != nil && strings.HasPrefix(err.Error(), "webrtc: ") {
	state := strings.TrimPrefix(err.Error(), "webrtc: ")
	if state == "failed" || state == "disconnected" {
		// exponential backoff retry with fresh offer
	}
}

Prevention

When it happens

Trigger: ICE negotiation failing (no usable candidates), DTLS handshake failure, remote peer closing the connection, or network change aborting the session between answer exchange and media flow.

Common situations: Camera/serving behind NAT without a working STUN/TURN path; firewall blocking UDP; WHEP server rejecting the session after setup; timeout waiting for the remote side.

Related errors


AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/c79522dfd9b409a5. Report an issue: GitHub.

Appendix: source

Thrown at internal/webrtc/client.go:116

	prod.Mode = core.ModeActiveProducer
	prod.Protocol = "ws"
	prod.URL = url
	prod.Listen(func(msg any) {
		switch msg := msg.(type) {
		case *pion.ICECandidate:
			s := msg.ToJSON().Candidate
			log.Trace().Str("candidate", s).Msg("[webrtc] local ")
			connMu.Lock()
			_ = conn.WriteJSON(&ws.Message{Type: "webrtc/candidate", Value: s})
			connMu.Unlock()

		case pion.PeerConnectionState:
			switch msg {
			case pion.PeerConnectionStateConnecting:
			case pion.PeerConnectionStateConnected:
				connState.Done(nil)
			default:
				connState.Done(errors.New("webrtc: " + msg.String()))
			}
		}
	})

	medias := []*core.Media{
		{Kind: core.KindVideo, Direction: core.DirectionRecvonly},
		{Kind: core.KindAudio, Direction: core.DirectionRecvonly},
		{Kind: core.KindAudio, Direction: core.DirectionSendonly},
	}

	// 3. Create offer
	offer, err := prod.CreateOffer(medias)
	if err != nil {
		return nil, err
	}

	// 4. Send offer
	msg := &ws.Message{Type: "webrtc/offer", Value: offer}

View on GitHub (pinned to c245815e75)