rust-lang/rust · error · NonIpSockAddr

Failed to convert address to SocketAddr: {}

Error message

Failed to convert address to SocketAddr: {}

What it means

Produced by Rust std's SGX (Intel Software Guard Extensions) network shim lookup_host_string. SGX enclaves have no network stack and no DNS resolver, so any address that is not already a literal IP address cannot be resolved to a SocketAddr. The NonIpSockAddr error wraps the offending host string; to_socket_addrs on an SGX target always fails for non-IP input.

Source

Thrown at library/std/src/sys/net/connection/sgx.rs:518

impl error::Error for NonIpSockAddr {}

impl fmt::Display for NonIpSockAddr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Failed to convert address to SocketAddr: {}", self.host)
    }
}

pub struct LookupHost(!);

impl Iterator for LookupHost {
    type Item = SocketAddr;
    fn next(&mut self) -> Option<SocketAddr> {
        self.0
    }
}

pub(crate) fn lookup_host_string(addr: impl Into<String>) -> io::Result<LookupHost> {
    Err(io::Error::new(io::ErrorKind::Uncategorized, NonIpSockAddr { host: addr.into() }))
}

pub fn lookup_host(host: &str, port: u16) -> io::Result<LookupHost> {
    lookup_host_string(format!("{host}:{port}"))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn unparseable_sockaddr() {
        let addr = "local";
        let error = addr.to_socket_addrs().unwrap_err();
        let non_ip_addr = error.downcast::<NonIpSockAddr>().unwrap();
        assert_eq!(addr, non_ip_addr.host);
    }
}

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. Pre-resolve the hostname outside the enclave and pass a literal IP:port string into the enclave.
  2. Use std::net::SocketAddr / Ipv4Addr::from(...) values constructed at compile time or supplied by the host application.
  3. Avoid APIs that call to_socket_addrs inside SGX; gate networking behind an ocalls-based host resolver.
  4. If you must accept hostnames, parse them to an IpAddr first and only connect when parsing succeeds.

Example fix

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

// after (inside SGX)
let addr: SocketAddr = ([93,184,216,34], 443).into();
let s = TcpStream::connect(addr)?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_literal_ip(host: &str) -> bool {
    host.parse::<std::net::IpAddr>().is_ok()
}
// Before connecting inside SGX:
if !is_literal_ip(host) {
    return Err("SGX requires a literal IP address".into());
}

Type guard

fn literal_socket_addr(s: &str) -> Option<std::net::SocketAddr> {
    s.parse().ok()
}

Try / catch

match (host, port).to_socket_addrs() {
    Ok(mut it) => Ok(it.next().unwrap()),
    Err(e) if e.downcast_ref::<NonIpSockAddr>().is_some() => {
        // ask host app for a pre-resolved IP
        Err("hostname not resolvable inside SGX".into())
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Calling to_socket_addrs() / TcpStream::connect / UdpSocket::bind with a hostname (e.g. "example.com:443") rather than a dotted-quad/IPv6 literal while running inside an SGX enclave. The call hits lookup_host_string which unconditionally returns NonIpSockAddr{ host }.

Common situations: Porting a networked crate into an SGX target; third-party dependency performing DNS; connecting to a service by name from within an enclave; tests run under the sgx unknown target.

Related errors


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