AlexxIT/go2rtc · error

av login 2 failed

Error message

av login 2 failed: %w

What it means

AVClientStart wraps a failure of the second DTLS write of the AV login handshake on the client side. The library sends two login packets to the camera; if the second Write fails, the underlying DTLS/TUTK transport error is wrapped with %w so the root cause (timeout, closed channel, IOTC error) is preserved. It indicates the AV login exchange could not complete.

Solutions

  1. Inspect the wrapped cause (%w / errors.Unwrap) to see if it is a timeout vs closed connection
  2. Retry AVClientStart with a fresh DialDTLS session — the old DTLS conn is likely dead
  3. Verify the camera is reachable and the connection is stable (check for packet loss)
  4. Check that AV login packet construction (pkt2) matches the camera firmware expectations

Example fix

// before
if _, err := c.clientConn.Write(pkt2); err != nil {
	return fmt.Errorf("av login 2 failed: %w", err)
}
// after
if _, err := c.clientConn.Write(pkt2); err != nil {
	if errors.Is(err, net.ErrClosed) || errors.Is(err, os.ErrDeadlineExceeded) {
		c.Close()
		return fmt.Errorf("av login 2 failed, session dead: %w", err)
	}
	return fmt.Errorf("av login 2 failed: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

if conn == nil || conn.IsClosed() {
	return fmt.Errorf("AV session not established")
}

Try / catch

err := conn.AVClientStart(timeout)
if err != nil {
	if errors.Is(err, os.ErrDeadlineExceeded) {
		// rebuild session then retry once
	}
	return err
}

Prevention

When it happens

Trigger: Calling AVClientStart (via doAVLogin) when the underlying channel write of the second login packet fails — DTLS session closed, camera dropped the connection between packet 1 and 2, or the TUTK channel errored.

Common situations: Camera rebooted or went offline mid-handshake; network drop over WAN; DTLS handshake succeeded but the camera closed the data channel because credentials/session were rejected; firewall dropping UDP after initial packets.

Related errors


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

Appendix: source

Thrown at pkg/tutk/dtls/conn_dtls.go:183

	go c.worker()

	return c, nil
}

func (c *DTLSConn) AVClientStart(timeout time.Duration) error {
	randomID := tutk.GenSessionID()
	pkt1 := c.msgAVLogin(magicAVLogin1, 570, 0x0001, randomID)
	pkt2 := c.msgAVLogin(magicAVLogin2, 572, 0x0000, randomID)
	pkt2[20]++ // pkt2 has randomID incremented by 1

	if _, err := c.clientConn.Write(pkt1); err != nil {
		return fmt.Errorf("av login 1 failed: %w", err)
	}

	time.Sleep(10 * time.Millisecond)

	if _, err := c.clientConn.Write(pkt2); err != nil {
		return fmt.Errorf("av login 2 failed: %w", err)
	}

	// Wait for response
	timer := time.NewTimer(timeout)
	defer timer.Stop()
	for {
		select {
		case data, ok := <-c.rawCmd:
			if !ok {
				return io.EOF
			}
			if len(data) >= 32 && binary.LittleEndian.Uint16(data) == magicAVLoginResp {
				c.hasTwoWayStreaming = data[31] == 1

				ack := c.msgACK()
				c.clientConn.Write(ack)

				// Start ACK sender for continuous streaming

View on GitHub (pinned to c245815e75)