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

  1. Retry the full Dial sequence with backoff — the handshake is session-scoped.
  2. Verify credentials are current; repeated K-stage timeouts can precede auth rejection elsewhere.
  3. Check that nothing else is closing the client/connection concurrently (race on the socket).
  4. 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

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)