tokio-rs/tokio · error · io::Error

could not resolve to any address

Error message

could not resolve to any address

What it means

TcpStream::connect resolves via to_socket_addrs, tries connect_addr on each, and uses unwrap_or_else to build this InvalidInput error only when last_err is None — meaning the resolved address iterator was empty. If candidates existed, the last connect error propagates instead. So this specific message means 'resolution returned no addresses to try.'

Source

Thrown at tokio/src/net/tcp/stream.rs:131

        ///
        /// The [`write_all`] method is defined on the [`AsyncWriteExt`] trait.
        ///
        /// [`write_all`]: fn@crate::io::AsyncWriteExt::write_all
        /// [`AsyncWriteExt`]: trait@crate::io::AsyncWriteExt
        pub async fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
            let addrs = to_socket_addrs(addr).await?;

            let mut last_err = None;

            for addr in addrs {
                match TcpStream::connect_addr(addr).await {
                    Ok(stream) => return Ok(stream),
                    Err(e) => last_err = Some(e),
                }
            }

            Err(last_err.unwrap_or_else(|| {
                io::Error::new(
                    io::ErrorKind::InvalidInput,
                    "could not resolve to any address",
                )
            }))
        }

        /// Establishes a connection to the specified `addr`.
        async fn connect_addr(addr: SocketAddr) -> io::Result<TcpStream> {
            let sys = mio::net::TcpStream::connect(addr)?;
            TcpStream::connect_mio(sys).await
        }

        pub(crate) async fn connect_mio(sys: mio::net::TcpStream) -> io::Result<TcpStream> {
            let stream = TcpStream::new(sys)?;

            // Once we've connected, wait for the stream to be writable as
            // that's when the actual connection has been initiated. Once we're
            // writable we check for `take_socket_error` to see if the connect

View on GitHub (pinned to 625954f365)

Solutions

  1. Pre-resolve with tokio::net::lookup_host to confirm addresses exist before connecting.
  2. Use happy-eyeballs / iterate the resolved list yourself to keep going past individual failures.
  3. Distinguish empty-resolution from connect-refused: empty → InvalidInput with no raw os error; refused → raw os error.
  4. Verify DNS externally (dig +short host) and fix or update the resolver.

Example fix

// before
let s = TcpStream::connect("svc.example:443").await?;

// after
let addrs: Vec<_> = tokio::net::lookup_host("svc.example:443").await?.collect();
if addrs.is_empty() {
    return Err(anyhow::anyhow!("svc.example resolved to no addresses"));
}
let mut last = None;
for a in addrs {
    match TcpStream::connect(a).await { Ok(s) => break Ok(s), Err(e) => last = Some(e) }
}
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 mut last = None;
for a in addrs {
    match TcpStream::connect(a).await { Ok(s) => return Ok(s), Err(e) => last = Some(e) }
}
Err(last.unwrap().into())

Type guard

fn is_empty_resolution(e: &io::Error) -> bool {
    e.kind() == io::ErrorKind::InvalidInput && e.raw_os_error().is_none()
}

Try / catch

match TcpStream::connect(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

When it happens

Trigger: Calling TcpStream::connect("host:port") where the hostname resolves to an empty A/AAAA set. The for loop never runs, last_err is None, and the fallback fires.

Common situations: Connecting to a typo'd or decommissioned hostname; bare CNAME with no A record; resolver / /etc/hosts returning an empty answer; a stale service-discovery entry pointing at a name with no records.

Related errors


AI-assisted analysis of tokio-rs/tokio@625954f365 (2026-08-11). Data as JSON: /api/errors/52429914145aa943. Report an issue: GitHub.