tokio-rs/tokio · error · io::Error
invalid address family (not IPv4 or IPv6)
Error message
invalid address family (not IPv4 or IPv6)
What it means
convert_address calls socket2::SockAddr::as_socket() and, when it returns None, errors with InvalidInput. as_socket() returns Some only for AF_INET / AF_INET6, so any other address family (Unix, Bluetooth, raw, etc.) falls through. The helper is used internally to normalize local/peer addresses obtained from the OS on a TcpSocket.
Source
Thrown at tokio/src/net/tcp/socket.rs:982
let raw_fd = std_stream.into_raw_fd();
unsafe { TcpSocket::from_raw_fd(raw_fd) }
}
#[cfg(windows)]
{
use std::os::windows::io::{FromRawSocket, IntoRawSocket};
let raw_socket = std_stream.into_raw_socket();
unsafe { TcpSocket::from_raw_socket(raw_socket) }
}
}
}
fn convert_address(address: socket2::SockAddr) -> io::Result<SocketAddr> {
match address.as_socket() {
Some(address) => Ok(address),
None => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"invalid address family (not IPv4 or IPv6)",
)),
}
}
impl fmt::Debug for TcpSocket {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(fmt)
}
}
// These trait implementations can't be build on Windows, so we completely
// ignore them, even when building documentation.
#[cfg(any(unix, target_os = "wasi"))]
cfg_unix_or_wasi! {
impl AsRawFd for TcpSocket {
fn as_raw_fd(&self) -> RawFd {View on GitHub (pinned to 625954f365)
Solutions
- Ensure the fd handed to TcpSocket was created as SOCK_STREAM over AF_INET/AF_INET6.
- Upgrade socket2 to a version matching the tokio build to avoid struct layout drift.
- Catch InvalidData here and fall back to a string-formatted address or refuse the connection.
- Reproduce with a minimal socket2-only test to isolate whether the OS or the binding is at fault.
Example fix
// before
let tcp = unsafe { TcpSocket::from_raw_socket(raw) };
let addr = tcp.peer_addr()?; // InvalidInput
// after
let tcp = unsafe { TcpSocket::from_raw_socket(raw) };
let addr = match tcp.peer_addr() {
Ok(a) => a,
Err(e) if e.kind() == io::ErrorKind::InvalidInput => {
return Err(anyhow::anyhow!("non-INET peer addr: {e}"));
}
Err(e) => return Err(e.into()),
}; Defensive patterns
Strategy: try-catch
Validate before calling
// Confirm the fd is INET before wrapping it:
use socket2::Socket;
let s = Socket::from(fd);
if s.local_addr().ok().and_then(|a| a.as_socket()).is_none() {
return Err(anyhow::anyhow!("fd is not an INET socket"));
} Type guard
fn is_non_inet_addr(e: &io::Error) -> bool {
e.kind() == io::ErrorKind::InvalidInput
} Try / catch
match tcp.peer_addr() {
Ok(a) => Ok(a),
Err(e) if e.kind() == io::ErrorKind::InvalidInput => {
Err(anyhow::anyhow!("non-INET peer address: {e}"))
}
Err(e) => Err(e.into()),
} Prevention
- Only feed TcpSocket fds that were created as SOCK_STREAM/AF_INET(6).
- Keep tokio and socket2 versions aligned to avoid struct drift.
- Reproduce suspected ABI issues in isolation against socket2 directly.
- Log the raw family value when you see this error to aid diagnosis.
When it happens
Trigger: Reading local_addr()/peer_addr() (or any path that calls convert_address) on a TcpSocket whose kernel-reported address family is neither IPv4 nor IPv6. Possible with an oddly-constructed fd, an ABI mismatch, or a socket inadvertently created from a non-INET family.
Common situations: Passing a non-INET raw fd into TcpSocket::from_raw_fd / from_raw_socket on Windows; a corrupted/mismatched socket2 version; AF that the OS returned is unexpected for a TCP socket. Rare in correct usage — usually indicates a programming or integration error.
Related errors
- could not resolve to any address
- could not resolve to any address
- could not resolve to any address
- no addresses to send data to
- sender not available
AI-assisted analysis of tokio-rs/tokio@625954f365 (2026-08-11).
Data as JSON: /api/errors/7d0d02f5978ee3dc.
Report an issue: GitHub.