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
- Check that ICE servers (STUN/TURN) are configured and reachable from both ends
- Verify UDP ports/firewall allow WebRTC traffic, or route through TURN
- Confirm the WHEP/signaling server session is still valid (token expiry)
- 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
- Configure reachable STUN/TURN servers
- Allow UDP traffic through firewalls or force TURN
- Validate signaling tokens are fresh before connecting
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)