{"record":{"id":"1ac2278424a96905","repo":"n0-computer/iroh","slug":"notconnected","errorCode":"NotConnected","errorMessage":"connection closed","messagePattern":"connection closed","errorType":"error_code","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"iroh/src/socket/transports.rs","lineNumber":1156,"sourceCode":"/// [`Socket`] which expands it back to one or more [`Addr`]s and sends it\n/// using the underlying [`Transports`].\n#[derive(Debug)]\n#[pin_project::pin_project]\npub(crate) struct Sender {\n    sock: Arc<Socket>,\n    #[pin]\n    sender: TransportsSender,\n}\n\nimpl Sender {\n    /// Extracts the right [`Addr`] from the [`noq_udp::Transmit`].\n    ///\n    /// Because Noq does only know about IP transports we map other transports to private\n    /// IPv6 Unique Local Address ranges.  This extracts the transport addresses out of the\n    /// transmit's destination.\n    fn mapped_addr(&self, transmit: &noq_udp::Transmit) -> io::Result<MultipathMappedAddr> {\n        if self.sock.is_closed() {\n            return Err(io::Error::new(\n                io::ErrorKind::NotConnected,\n                \"connection closed\",\n            ));\n        }\n\n        Ok(MultipathMappedAddr::from(transmit.destination))\n    }\n}\n\nimpl noq::UdpSender for Sender {\n    fn poll_send(\n        self: Pin<&mut Self>,\n        noq_transmit: &noq_udp::Transmit,\n        cx: &mut Context,\n    ) -> Poll<io::Result<()>> {\n        // On errors this methods prefers returning Ok(()) to Noq.  Returning an error\n        // should only happen if the error is permanent and fatal and it will never be\n        // possible to send anything again.  Doing so kills the Noq EndpointDriver.  Most","sourceCodeStart":1138,"sourceCodeEnd":1174,"githubUrl":"https://github.com/n0-computer/iroh/blob/2b4de030ce5e0133f272871a76f0c685c63f552a/iroh/src/socket/transports.rs#L1138-L1174","documentation":"The noq multipath socket wrapper was asked to map a transmit's destination address while its underlying UDP socket was already closed. mapped_addr returns io::ErrorKind::NotConnected with 'connection closed' because sends can no longer be performed on a closed socket.","triggerScenarios":"Transmitting a packet through the transport after the socket has been closed (sock.is_closed() == true) — typically when the endpoint/transport was shut down but a queued send or poll still references it.","commonSituations":"Endpoint dropped/closed while in-flight packets are still being flushed, shutdown ordering issues where the QUIC connection outlives its socket, cancelled tasks racing with socket close.","solutions":["Ensure the QUIC endpoint/connection is fully shut down before closing the underlying UDP socket.","Stop issuing transmits once the transport reports closed; treat NotConnected as terminal.","Check for tasks holding the socket handle after shutdown and drop them.","Guard sends with a liveness/connected check on the transport handle."],"exampleFix":"// before\nsock.send(transmit)?; // may hit closed socket\n// after\nif sock.is_closed() { return; }\nsock.send(transmit)?;","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn sendable(sock: &MultipathSock, t: &Transmit) -> Result<(), std::io::Error> {\n    if sock.is_closed() { Err(std::io::Error::new(std::io::ErrorKind::NotConnected, \"connection closed\")) } else { Ok(()) }\n}","tryCatchPattern":"match sock.send(transmit) {\n    Err(e) if e.kind() == std::io::ErrorKind::NotConnected => { /* socket shut down: stop sending */ }\n    other => other?,\n}","preventionTips":["Shut down connections before closing the underlying socket.","Drop sender tasks during teardown to avoid racing sends.","Treat NotConnected as terminal; never retry on a closed socket.","Structure shutdown with an ordered close sequence."],"tags":["socket","not-connected","shutdown","quic"],"backgroundTag":"not-connected","analyzedSha":"2b4de030ce5e0133f272871a76f0c685c63f552a","analyzedAt":"2026-09-08T04:26:47.755Z","contentChangedAt":"2026-09-08T04:26:47.755Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}