tokio-rs/tokio · error · io::Error
connect cannot be called on a datagram socket
Error message
connect cannot be called on a datagram socket
What it means
UnixSocket::connect checks ty(); if it's socket2::Type::DGRAM, it returns io::ErrorKind::Other 'connect cannot be called on a datagram socket' before issuing the kernel connect(2). For DGRAM sockets the connectionless connect semantics differ; tokio reserves connect for stream sockets. The doc states this explicitly for new_datagram-created sockets.
Source
Thrown at tokio/src/net/unix/socket.rs:203
};
UnixListener::new(mio)
}
/// Establishes a Unix connection with a peer at the specified socket address.
///
/// The `UnixSocket` is consumed. Once the connection is established, a
/// connected [`UnixStream`] is returned. If the connection fails, the
/// encountered error is returned.
///
/// Calling this function on a socket created by [`new_datagram`] will return an error.
///
/// This calls the `connect(2)` operating-system function.
///
/// [`new_datagram`]: `UnixSocket::new_datagram`
pub async fn connect(self, path: impl AsRef<Path>) -> io::Result<UnixStream> {
if self.ty() == socket2::Type::DGRAM {
return Err(io::Error::new(
io::ErrorKind::Other,
"connect cannot be called on a datagram socket",
));
}
let addr = socket2::SockAddr::unix(path)?;
if let Err(err) = self.inner.connect(&addr) {
if err.raw_os_error() != Some(libc::EINPROGRESS) {
return Err(err);
}
}
let mio = {
use std::os::unix::io::{FromRawFd, IntoRawFd};
let raw_fd = self.inner.into_raw_fd();
unsafe { mio::net::UnixStream::from_raw_fd(raw_fd) }
};
View on GitHub (pinned to 625954f365)
Solutions
- Use UnixSocket::new_stream() if you need a connected stream, then call connect().
- For datagram exchange, use UnixDatagram::bind / connect (the UnixDatagram API supports a connect-like default-peer) instead of UnixSocket::connect.
- Branch on socket type and pick the right client API accordingly.
- Add a unit test asserting the socket type matches the call path to catch refactor regressions.
Example fix
// before
let s = UnixSocket::new_datagram()?;
s.connect("/tmp/dgram.sock").await?; // error
// after
let s = UnixSocket::new_stream()?;
let conn = s.connect("/tmp/stream.sock").await?; Defensive patterns
Strategy: type-guard
Validate before calling
let s = UnixSocket::new_stream()?; // for connect semantics // If you have an existing fd, check socket2::Type before calling connect.
Type guard
fn is_connect_on_datagram(e: &io::Error) -> bool {
e.kind() == io::ErrorKind::Other
&& e.to_string() == "connect cannot be called on a datagram socket"
} Try / catch
match sock.connect(path).await {
Ok(c) => Ok(c),
Err(e) if e.to_string() == "connect cannot be called on a datagram socket" => {
Err(anyhow::anyhow!("use UnixDatagram for datagram sockets"))
}
Err(e) => Err(e.into()),
} Prevention
- Use new_stream() when you need connection-oriented connect.
- For datagram default-peer, use UnixDatagram::connect, not UnixSocket::connect.
- Branch on socket type before choosing the client API.
- Unit-test the type/method pairing to catch refactor regressions.
When it happens
Trigger: Calling UnixSocket::connect(path) on a socket built with UnixSocket::new_datagram().
Common situations: Reusing a stream-client template on a datagram socket; protocol role confusion; refactoring that changed socket type without updating the connect call.
Related errors
- listen cannot be called on a datagram socket
- datagram cannot be called on a stream socket
- invalid address family (not IPv4 or IPv6)
- could not resolve to any address
- not a pipe
AI-assisted analysis of tokio-rs/tokio@625954f365 (2026-08-11).
Data as JSON: /api/errors/1dbe33dbdf2a24a1.
Report an issue: GitHub.