{"record":{"id":"d45ed377dd097186","repo":"AlexxIT/go2rtc","slug":"av-login-1-failed-w","errorCode":null,"errorMessage":"av login 1 failed: %w","messagePattern":"av login 1 failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/tutk/dtls/conn_dtls.go","lineNumber":177,"sourceCode":"\tif err = c.connect(); err != nil {\n\t\t_ = c.Close()\n\t\treturn nil, err\n\t}\n\n\tc.wg.Add(1)\n\tgo c.worker()\n\n\treturn c, nil\n}\n\nfunc (c *DTLSConn) AVClientStart(timeout time.Duration) error {\n\trandomID := tutk.GenSessionID()\n\tpkt1 := c.msgAVLogin(magicAVLogin1, 570, 0x0001, randomID)\n\tpkt2 := c.msgAVLogin(magicAVLogin2, 572, 0x0000, randomID)\n\tpkt2[20]++ // pkt2 has randomID incremented by 1\n\n\tif _, err := c.clientConn.Write(pkt1); err != nil {\n\t\treturn fmt.Errorf(\"av login 1 failed: %w\", err)\n\t}\n\n\ttime.Sleep(10 * time.Millisecond)\n\n\tif _, err := c.clientConn.Write(pkt2); err != nil {\n\t\treturn fmt.Errorf(\"av login 2 failed: %w\", err)\n\t}\n\n\t// Wait for response\n\ttimer := time.NewTimer(timeout)\n\tdefer timer.Stop()\n\tfor {\n\t\tselect {\n\t\tcase data, ok := <-c.rawCmd:\n\t\t\tif !ok {\n\t\t\t\treturn io.EOF\n\t\t\t}\n\t\t\tif len(data) >= 32 && binary.LittleEndian.Uint16(data) == magicAVLoginResp {","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/tutk/dtls/conn_dtls.go#L159-L195","documentation":"AVClientStart performs a two-stage AV login by writing two crafted login packets to the client connection. If the first packet write fails, the error is wrapped as 'av login 1 failed: %w' preserving the underlying cause. This is a transport-level failure, not an application-level login rejection.","triggerScenarios":"Calling AVClientStart (via doAVLogin) when c.clientConn.Write(pkt1) returns an error — connection closed, DTLS/UDP write failure, or the underlying session already dead.","commonSituations":"Device went offline between connect and login; underlying DTLS handshake/transport not ready; firewall blocking outbound packets; session torn down by a previous timeout while the object is reused.","solutions":["Inspect the wrapped error (%w) to identify the transport cause and fix it (reconnect, re-handshake, network).","Re-create the connection (Dial + DTLS handshake) before retrying AVClientStart — writes on a dead conn will keep failing.","Verify the device is reachable and its AV server port is open before initiating login.","Add retry with backoff around AVClientStart for transient network blips."],"exampleFix":"// before\nif err := doAVLogin(conn); err != nil { return err }\n// after\nif err := doAVLogin(conn); err != nil {\n\tconn, cerr := redial() // fresh Dial + handshake\n\tif cerr != nil { return cerr }\n\treturn doAVLogin(conn)\n}","handlingStrategy":"retry","validationCode":"// Ensure transport is writable before login\nif err := conn.Ping(); err != nil {\n\treturn fmt.Errorf(\"transport not ready for AV login: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"err := doAVLogin(conn)\nif err != nil && strings.Contains(err.Error(), \"av login 1 failed\") {\n\tconn, rerr := redial() // fresh Dial + handshake\n\tif rerr != nil { return rerr }\n\treturn retry.Do(3, time.Second, func() error { return doAVLogin(conn) })\n}","preventionTips":["Verify device reachability before initiating AV login","Redial dead sessions instead of reusing them","Add retry with backoff around login for transient blips","Log the wrapped transport error to distinguish offline vs blocked"],"tags":["tutk","dtls","network","login"],"backgroundTag":"http-request-failed","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}