AlexxIT/go2rtc · error
wyze: K10002 failed
Error message
wyze: K10002 failed: %w
What it means
doKAuth step 2 sends the K10002 auth request (challenge + status) and waits for the K10003 result via WriteAndWaitIOCtrl (5s). Failure of the write/IO-ctrl exchange (timeout, dead socket) is wrapped as "wyze: K10002 failed".
Solutions
- Retry the full Dial sequence with backoff — the handshake is session-scoped.
- Verify credentials are current; repeated K-stage timeouts can precede auth rejection elsewhere.
- Check that nothing else is closing the client/connection concurrently (race on the socket).
- Ensure network stability; timeouts here usually indicate packet loss to the camera.
Defensive patterns
Strategy: retry
Try / catch
if err := client.Dial(); err != nil {
if strings.Contains(err.Error(), "K10002 failed") {
time.Sleep(time.Second)
err = client.Dial() // restart the whole handshake
}
if err != nil {
return err
}
} Prevention
- Retry the complete Dial sequence with backoff
- Ensure the network path to the camera is stable before auth
- Don't Close the client concurrently during handshake
When it happens
Trigger: Camera does not reply with KCmdAuthResult within 5 seconds; underlying DTLS socket closed between K10001 and K10002; camera rejected the session before evaluating credentials.
Common situations: Flaky Wi-Fi dropping the tunnel mid-handshake; camera busy/streaming to another client and slow to respond; camera firmware stalling the auth exchange.
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/8e01cf8a9f666102.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/wyze/client.go:355
data, err := c.conn.WriteAndWaitIOCtrl(c.buildK10000(), c.matchHL(KCmdChallenge), 5*time.Second)
if err != nil {
return fmt.Errorf("wyze: K10001 failed: %w", err)
}
hlData := c.extractHL(data)
challenge, status, err := c.parseK10001(hlData)
if err != nil {
return fmt.Errorf("wyze: K10001 parse failed: %w", err)
}
if c.verbose {
fmt.Printf("[Wyze] K10001 challenge received, status=%d\n", status)
}
// Step 2: K10002 -> K10003 (Auth)
data, err = c.conn.WriteAndWaitIOCtrl(c.buildK10002(challenge, status), c.matchHL(KCmdAuthResult), 5*time.Second)
if err != nil {
return fmt.Errorf("wyze: K10002 failed: %w", err)
}
hlData = c.extractHL(data)
// Parse K10003 response
authResp, err := c.parseK10003(hlData)
if err != nil {
return fmt.Errorf("wyze: K10003 parse failed: %w", err)
}
if c.verbose && authResp != nil {
if jsonBytes, err := json.MarshalIndent(authResp, "", " "); err == nil {
fmt.Printf("[Wyze] K10003 response:\n%s\n", jsonBytes)
}
}
// Extract audio capability from cameraInfo
if authResp != nil && authResp.CameraInfo != nil {
if channelResult, ok := authResp.CameraInfo["channelRequestResult"].(map[string]any); ok {View on GitHub (pinned to c245815e75)