tokio-rs/tokio · error · io::Error
could not resolve to any address
Error message
could not resolve to any address
What it means
UdpSocket::bind follows the same pattern as the TCP variants: resolve, iterate, fall back to this InvalidInput error only when last_err is None. That branch is reached exclusively when to_socket_addrs returned an empty iterator — no addresses to attempt a bind against.
Source
Thrown at tokio/src/net/udp.rs:162
/// let sock = UdpSocket::bind("0.0.0.0:8080").await?;
/// // use `sock`
/// # let _ = sock;
/// Ok(())
/// }
/// ```
pub async fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
let addrs = to_socket_addrs(addr).await?;
let mut last_err = None;
for addr in addrs {
match UdpSocket::bind_addr(addr) {
Ok(socket) => return Ok(socket),
Err(e) => last_err = Some(e),
}
}
Err(last_err.unwrap_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
"could not resolve to any address",
)
}))
}
fn bind_addr(addr: SocketAddr) -> io::Result<UdpSocket> {
let sys = mio::net::UdpSocket::bind(addr)?;
UdpSocket::new(sys)
}
#[track_caller]
fn new(socket: mio::net::UdpSocket) -> io::Result<UdpSocket> {
let io = PollEvented::new(socket)?;
Ok(UdpSocket { io })
}
/// Creates new `UdpSocket` from a previously bound `std::net::UdpSocket`.View on GitHub (pinned to 625954f365)
Solutions
- Bind to a literal IP (e.g. "0.0.0.0:port" or "127.0.0.1:port") — the recommended idiom for UDP listeners.
- Pre-resolve with tokio::net::lookup_host and assert non-empty before binding.
- Inspect the error: InvalidInput with no raw_os_error means empty resolution; otherwise a real bind error.
- Validate the hostname with an external resolver (dig/nslookup).
Example fix
// before
let s = UdpSocket::bind("my-svc:9090").await?;
// after
let s = UdpSocket::bind(("0.0.0.0", 9090)).await?;
// or check resolution explicitly:
if tokio::net::lookup_host("my-svc:9090").await?.next().is_none() {
return Err(anyhow::anyhow!("no addresses for my-svc"));
} Defensive patterns
Strategy: validation
Validate before calling
let addrs: Vec<_> = tokio::net::lookup_host((host.as_str(), port)).await?.collect();
if addrs.is_empty() {
return Err(anyhow::anyhow!("{host} resolved to no addresses"));
}
let s = UdpSocket::bind(addrs[0]).await?; Type guard
fn is_empty_resolution(e: &io::Error) -> bool {
e.kind() == io::ErrorKind::InvalidInput && e.raw_os_error().is_none()
} Try / catch
match UdpSocket::bind(addr).await {
Ok(s) => Ok(s),
Err(e) if e.kind() == io::ErrorKind::InvalidInput && e.raw_os_error().is_none() => {
Err(anyhow::anyhow!("no addresses resolved for {addr}"))
}
Err(e) => Err(e.into()),
} Prevention
- Bind UDP listeners to literal IPs, not hostnames.
- Pre-resolve and confirm non-empty before binding.
- Distinguish empty resolution from real bind errors by checking raw_os_error.
- Validate hostnames at config load time.
When it happens
Trigger: Calling UdpSocket::bind("host:port") where the hostname resolves to zero A/AAAA records, so the for loop body never executes and last_err stays None.
Common situations: Bad hostname; service with no A record; misconfigured DNS or /etc/hosts; binding by name to a host that no longer exists; passing a name where a literal IP is intended.
Related errors
- could not resolve to any address
- no addresses to send data to
- could not resolve to any address
- sender not available
- failed to write entire datagram to socket
AI-assisted analysis of tokio-rs/tokio@625954f365 (2026-08-11).
Data as JSON: /api/errors/291544047b24f9ec.
Report an issue: GitHub.