AlexxIT/go2rtc · error

can't connect

Error message

can't connect

What it means

After exchanging SDP and ICE candidates, Connect waits on a `connected` channel for the final result of the WebRTC handshake. A `false` value (peer connection failed to establish) yields "can't connect".

Solutions

  1. Check UDP connectivity/firewall between client and camera network
  2. Retry the connection; transient ICE failures are common
  3. Make sure the camera is not occupied by another viewer
  4. Update device firmware via the Roborock app
Defensive patterns

Strategy: retry

Validate before calling

if !udpOutboundAllowed() {
    return errors.New("roborock camera streaming requires outbound UDP for WebRTC")
}

Try / catch

err := client.Connect(ctx)
if err != nil && err.Error() == "can't connect" {
    if err = retryConnect(ctx, client, 3); err != nil {
        return fmt.Errorf("webrtc to camera failed: %w", err)
    }
}

Prevention

When it happens

Trigger: The WebRTC peer connection with the roborock camera signals failure instead of success — ICE candidates never connect, DTLS handshake fails, or the camera aborts the session.

Common situations: Network/NAT incompatibility preventing UDP connectivity to the camera; camera rejecting the offer because it is busy; firmware not supporting the negotiated media.

Related errors


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

Appendix: source

Thrown at pkg/roborock/client.go:194

	for {
		select {
		case <-ticker.C:
			// 7. Receive remote candidates
			if pc.ICEConnectionState() == pion.ICEConnectionStateCompleted {
				ticker.Stop()
				continue
			}

			if ice, _ := c.GetDeviceICE(); ice != nil {
				for _, candidate := range ice {
					_ = c.conn.AddCandidate(candidate)
				}
			}

		case ok := <-connected:
			// 8. Wait connected result (true or false)
			if !ok {
				return errors.New("can't connect")
			}

			return nil
		}
	}
}

func (c *Client) CheckHomesecPassword() (err error) {
	var ok bool

	params := `{"password":"` + c.pin + `"}`
	if err = c.iot.Call("check_homesec_password", params, &ok); err != nil {
		return
	}

	if !ok {
		return errors.New("wrong pin code")
	}

View on GitHub (pinned to c245815e75)