rust-lang/rust · error · io::Error

failed to lookup address information: {detail}

Error message

failed to lookup address information: {detail}

What it means

Returned by Rust std's unix getaddrinfo wrapper when libc getaddrinfo reports a failure. It special-cases EAI_SYSTEM (returns last_os_error instead) and otherwise renders libc::gai_strerror(err) as the detail string. On espidf/nuttx the detail is empty. ErrorKind is Uncategorized.

Source

Thrown at library/std/src/sys/net/connection/socket/unix.rs:59

    // We may need to trigger a glibc workaround. See on_resolver_failure() for details.
    on_resolver_failure();

    #[cfg(not(any(target_os = "espidf", target_os = "nuttx")))]
    if err == libc::EAI_SYSTEM {
        return Err(io::Error::last_os_error());
    }

    #[cfg(not(any(target_os = "espidf", target_os = "nuttx")))]
    let detail = unsafe {
        // We can't always expect a UTF-8 environment. When we don't get that luxury,
        // it's better to give a low-quality error message than none at all.
        CStr::from_ptr(libc::gai_strerror(err)).to_string_lossy()
    };

    #[cfg(any(target_os = "espidf", target_os = "nuttx"))]
    let detail = "";

    Err(io::Error::new(
        io::ErrorKind::Uncategorized,
        &format!("failed to lookup address information: {detail}")[..],
    ))
}

impl Socket {
    pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
        cfg_select! {
            any(
                target_os = "android",
                target_os = "dragonfly",
                target_os = "freebsd",
                target_os = "illumos",
                target_os = "hurd",
                target_os = "linux",
                target_os = "netbsd",
                target_os = "openbsd",
                target_os = "cygwin",

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. Inspect the detail string: 'Name or service not known' -> fix hostname; 'Temporary failure in name resolution' -> retry with backoff.
  2. Ensure /etc/resolv.conf and /etc/nsswitch.conf exist and name a reachable nameserver.
  3. Test with `getent hosts <name>` or `dig <name>` to isolate resolver vs application issues.
  4. Fall back to a cached/literal IP address or implement a retry policy for transient failures.

Example fix

// before
match ("api.example.com", 443).to_socket_addrs() {
    Ok(_) => {},
    Err(e) => panic!("{e}"),
}

// after
use std::time::Duration;
let mut last = None;
for _ in 0..3 {
    match ("api.example.com", 443).to_socket_addrs() {
        Ok(it) => { /* use it */ break; }
        Err(e) => { last = Some(e); std::thread::sleep(Duration::from_secs(2)); }
    }
}
Defensive patterns

Strategy: retry

Validate before calling

fn lookup_with_fallback(host: &str, port: u16) -> io::Result<std::net::SocketAddr> {
    if let Ok(ip) = host.parse::<std::net::IpAddr>() {
        return Ok(std::net::SocketAddr::new(ip, port));
    }
    (host, port).to_socket_addrs()?.next()
        .ok_or_else(|| io::Error::new(io::ErrorKind::Uncategorized, "no addr"))
}

Try / catch

use std::time::Duration;
let mut last = None;
for _ in 0..3 {
    match (host, port).to_socket_addrs() {
        Ok(mut it) => return Ok(it.next().unwrap()),
        Err(e) if e.to_string().contains("Temporary failure") => {
            last = Some(e); std::thread::sleep(Duration::from_secs(2));
        }
        Err(e) => return Err(e),
    }
}
Err(last.unwrap())

Prevention

When it happens

Trigger: Any DNS resolution that fails on a unix-like target: NXDOMAIN, no resolver configured, /etc/hosts/ resolv.conf missing, temporary resolver outage, unsupported family, or service-name unknown. Reached through to_socket_addrs, TcpStream::connect, UdpSocket::bind with a hostname.

Common situations: Container/chroot without /etc/resolv.conf; DNS server down; transient network loss; typo in hostname; IPv6 lookup on IPv4-only host; sandbox blocking the resolver syscall.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/c94460b293cb4e56. Report an issue: GitHub.