AlexxIT/go2rtc · error
can't get device SDP
Error message
can't get device SDP
What it means
Roborock Connect timeout: after sending the WebRTC offer, the client polled GetDeviceSDP every second for 5 seconds without receiving the device's answer SDP. The vacuum did not answer signaling in time, so SetAnswer was never possible and Connect gives up.
Solutions
- Verify the device is online and responsive in the Roborock app
- Retry Connect once the device wakes up (off dock / out of sleep)
- Increase the SDP wait deadline if your network is slow
- Ensure no competing streaming session holds the camera
Defensive patterns
Strategy: retry
Validate before calling
if status, _ := c.GetHomesecConnectStatus(); status == "" {
return errors.New("device not reachable for SDP exchange")
} Try / catch
err := client.Connect(ctx)
if err != nil && err.Error() == "can't get device SDP" {
time.Sleep(5 * time.Second)
err = client.Connect(ctx)
} Prevention
- Wake the device / confirm it is docked-online before dialing
- Use a reliable low-latency MQTT path to the device
- Increase the SDP timeout on slow networks
When it happens
Trigger: The Roborock IoT call requesting the device SDP gets no response before the deadline — device offline, slow to respond, or the MQTT/RPC channel to the camera stalls.
Common situations: Robot vacuum sleeping or out of dock connectivity; weak Wi-Fi on the device; camera busy with another session so it ignores the SDP request.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/c62526bc996ffd45.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/roborock/client.go:171
}
sendOffer.Done()
// 6. Receive answer
ts := time.Now().Add(time.Second * 5)
for {
time.Sleep(time.Second)
if desc, _ := c.GetDeviceSDP(); desc != nil {
//log.Printf("[roborock] answer\n%s", desc.SDP)
if err = c.conn.SetAnswer(desc.SDP); err != nil {
return err
}
break
}
if time.Now().After(ts) {
return errors.New("can't get device SDP")
}
}
ticker := time.NewTicker(time.Second * 2)
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)
}
}View on GitHub (pinned to c245815e75)