{"record":{"id":"20c77af8b695fdc7","repo":"tokio-rs/tokio","slug":"sender-not-available","errorCode":null,"errorMessage":"sender not available","messagePattern":"sender not available","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"warning","filePath":"tokio/src/net/udp.rs","lineNumber":1892,"sourceCode":"    /// It is important to be aware of this when designing your application-level protocol.\n    ///\n    /// [packet injection attack]: https://en.wikipedia.org/wiki/Packet_injection\n    pub fn try_peek_sender(&self) -> io::Result<SocketAddr> {\n        self.io\n            .registration()\n            .try_io(Interest::READABLE, || self.peek_sender_inner())\n    }\n\n    #[inline]\n    fn peek_sender_inner(&self) -> io::Result<SocketAddr> {\n        self.io.try_io(|| {\n            self.as_socket()\n                .peek_sender()?\n                // May be `None` if the platform doesn't populate the sender for some reason.\n                // In testing, that only occurred on macOS if you pass a zero-sized buffer,\n                // but the implementation of `Socket::peek_sender()` covers that.\n                .as_socket()\n                .ok_or_else(|| io::Error::new(io::ErrorKind::Other, \"sender not available\"))\n        })\n    }\n\n    /// Gets the value of the `SO_BROADCAST` option for this socket.\n    ///\n    /// For more information about this option, see [`set_broadcast`].\n    ///\n    /// [`set_broadcast`]: method@Self::set_broadcast\n    pub fn broadcast(&self) -> io::Result<bool> {\n        self.io.broadcast()\n    }\n\n    /// Sets the value of the `SO_BROADCAST` option for this socket.\n    ///\n    /// When enabled, this socket is allowed to send packets to a broadcast\n    /// address.\n    pub fn set_broadcast(&self, on: bool) -> io::Result<()> {\n        self.io.set_broadcast(on)","sourceCodeStart":1874,"sourceCodeEnd":1910,"githubUrl":"https://github.com/tokio-rs/tokio/blob/625954f365727668cb02d04172b34f1149637728/tokio/src/net/udp.rs#L1874-L1910","documentation":"peek_sender_inner calls Socket::peek_sender() then converts via .as_socket(); when as_socket() returns None (the platform didn't populate a recognizable IPv4/IPv6 source), tokio returns this io::ErrorKind::Other error. The code comment notes that during testing this was only seen on macOS with a zero-sized receive buffer. It is a defensive guard for an ill-formed control message.","triggerScenarios":"Calling UdpSocket::peek_sender() (or the underlying try_io) on a socket where the kernel returns a recvmsg ancillary sender that doesn't decode to an INET address. The doc note calls out macOS + zero-sized buffer as the observed cause.","commonSituations":"macOS only; passing a zero-length buffer to peek_sender; exotic platforms whose msg_name is malformed; ABI quirks in socket2 on specific macOS versions.","solutions":["Pass a non-zero buffer to peek_sender (the receive path still needs somewhere to put bytes).","On macOS, use recv_from instead of peek_sender if you need the sender with a zero-byte probe.","Handle io::ErrorKind::Other with this message as a soft failure — log and skip rather than tearing down the socket.","Upgrade socket2/tokio to pick up any platform fixes for msg_name population."],"exampleFix":"// before\nlet peer = sock.peek_sender().await?; // 'sender not available' on macOS\n\n// after\nlet peer = match sock.peek_sender().await {\n    Ok(p) => p,\n    Err(e) if e.to_string() == \"sender not available\" => {\n        // fall back to a real recv to learn the peer\n        let mut buf = [0u8; 1];\n        let (_, p) = sock.recv_from(&mut buf).await?;\n        p\n    }\n    Err(e) => return Err(e.into()),\n};","handlingStrategy":"try-catch","validationCode":"// Pass a non-zero buffer to peek_sender; on macOS avoid zero-byte probes.\n// (No pure pre-check exists; guard at the call site.)","typeGuard":"fn is_sender_unavailable(e: &io::Error) -> bool {\n    e.kind() == io::ErrorKind::Other && e.to_string() == \"sender not available\"\n}","tryCatchPattern":"match sock.peek_sender().await {\n    Ok(p) => Ok(p),\n    Err(e) if e.to_string() == \"sender not available\" => {\n        let mut buf = [0u8; 1];\n        let (_, p) = sock.recv_from(&mut buf).await?;\n        Ok(p)\n    }\n    Err(e) => Err(e.into()),\n}","preventionTips":["Always pass a non-zero buffer when probing the sender on macOS.","Prefer recv_from over peek_sender for zero-byte probes on Apple platforms.","Keep tokio and socket2 up to date for msg_name handling fixes.","Treat this as a soft, platform-specific failure rather than fatal."],"tags":["net","udp","peek","macos","tokio"],"backgroundTag":null,"analyzedSha":"625954f365727668cb02d04172b34f1149637728","analyzedAt":"2026-08-11T17:46:45.378Z","contentChangedAt":"2026-08-11T17:46:45.378Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}