{"record":{"id":"5ab3d3e010b2f940","repo":"lima-vm/lima","slug":"udpfileconn-connection-closed","errorCode":null,"errorMessage":"UDPFileConn connection closed","messagePattern":"UDPFileConn connection closed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"pkg/networks/usernet/udpfileconn.go","lineNumber":20,"sourceCode":"// SPDX-License-Identifier: Apache-2.0\n\npackage usernet\n\nimport (\n\t\"errors\"\n\t\"net\"\n\t\"time\"\n)\n\ntype UDPFileConn struct {\n\tnet.Conn\n}\n\nfunc (conn *UDPFileConn) Read(b []byte) (n int, err error) {\n\t// Check if the connection has been closed\n\tif err := conn.SetReadDeadline(time.Time{}); err != nil {\n\t\tif errors.Is(err, net.ErrClosed) {\n\t\t\treturn 0, errors.New(\"UDPFileConn connection closed\")\n\t\t}\n\t}\n\treturn conn.Conn.Read(b)\n}\n","sourceCodeStart":2,"sourceCodeEnd":25,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/networks/usernet/udpfileconn.go#L2-L25","documentation":"UDPFileConn wraps a net.Conn and its Read first probes the connection by clearing the read deadline; if the underlying connection is already closed, the probe returns net.ErrClosed and Read converts it into the literal error \"UDPFileConn connection closed\" instead of attempting a read on a dead socket.","triggerScenarios":"A goroutine calls UDPFileConn.Read after the connection's Close() was called (e.g. the usernet daemon shut down or the peer handler closed the socket while a reader loop was still active).","commonSituations":"Hostagent or guestagent connection handler closing the UDP socket while a relay/packet-reading loop is concurrently blocked on Read; daemon shutdown racing with active connections.","solutions":["Treat this error as a normal shutdown signal: break the read loop and return without retrying.","Synchronize: only call Read while the connection is open; signal readers via a done channel before calling Close().","Use errors.Is-style comparison or string match on the returned error to detect closure and exit the loop cleanly.","If you need the underlying net.ErrClosed, check conn.SetReadDeadline yourself before relying on Read."],"exampleFix":"// before\nfor {\n\tn, err := udpConn.Read(buf)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n// after\nfor {\n\tn, err := udpConn.Read(buf)\n\tif err != nil {\n\t\tif err.Error() == \"UDPFileConn connection closed\" || errors.Is(err, net.ErrClosed) {\n\t\t\treturn nil // graceful shutdown\n\t\t}\n\t\treturn err\n\t}\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isConnClosed(err) {\n  return err != null && (err.message === 'UDPFileConn connection closed' ||\n    (typeof err.unwrap === 'function' && err === null) || /connection closed/i.test(err.message));\n}","tryCatchPattern":"n, err := conn.Read(buf)\nif err != nil {\n\tif err.Error() == \"UDPFileConn connection closed\" || errors.Is(err, net.ErrClosed) {\n\t\treturn nil // expected during shutdown\n\t}\n\treturn err\n}","preventionTips":["Close connections only after all reader goroutines have stopped (use a done channel/WaitGroup).","Treat this error as a graceful-shutdown signal, not a failure.","Avoid reading from the conn after calling Close in any code path.","Centralize connection lifecycle ownership in one component."],"tags":["network","udp","connection-closed","usernet"],"backgroundTag":"connection-closed","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}