{"record":{"id":"a1555eb0e1d91124","repo":"jpochyla/psst","slug":"could-not-resolve-to-any-addresses","errorCode":null,"errorMessage":"could not resolve to any addresses","messagePattern":"could not resolve to any addresses","errorType":"error_code","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"psst-core/src/connection/mod.rs","lineNumber":215,"sourceCode":"        }\n        log::error!(\"failed to connect to any access point\");\n        Err(Error::ConnectionFailed)\n    }\n\n    fn stream_without_proxy(ap: &str) -> Result<TcpStream, io::Error> {\n        let mut last_err = None;\n        for addr in ap.to_socket_addrs()? {\n            match TcpStream::connect_timeout(&addr, NET_CONNECT_TIMEOUT) {\n                Ok(stream) => {\n                    return Ok(stream);\n                }\n                Err(err) => {\n                    last_err.replace(err);\n                }\n            }\n        }\n        Err(last_err.unwrap_or_else(|| {\n            io::Error::new(\n                io::ErrorKind::InvalidInput,\n                \"could not resolve to any addresses\",\n            )\n        }))\n    }\n\n    fn stream_through_proxy(ap: &str, url: &str) -> Result<TcpStream, Error> {\n        match Url::parse(url) {\n            Ok(url) if url.scheme() == \"socks\" || url.scheme() == \"socks5\" => {\n                // Currently we only support SOCKS5 proxies.\n                Self::stream_through_socks5_proxy(ap, &url)\n            }\n            _ => {\n                // Proxy URL failed to parse or has unsupported scheme.\n                Err(Error::ProxyUrlInvalid)\n            }\n        }\n    }","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/jpochyla/psst/blob/3c3621aa79f820c737dd899e7e359b1359292466/psst-core/src/connection/mod.rs#L197-L233","documentation":"This io::Error (ErrorKind::InvalidInput) is produced by `stream_without_proxy` when `ap.to_socket_addrs()` resolves successfully but yields zero addresses, so the TCP connect loop never runs and no per-attempt error was recorded. It means the access-point hostname/port string could not be turned into any usable SocketAddr. It is the fallback branch (psst-core/src/connection/mod.rs:214-219) that normally would carry the last connect failure instead.","triggerScenarios":"Calling `Connection::connect(ap_list, None)` (which calls `stream_without_proxy`) with an access point string that DNS-resolves to an empty address list — e.g. an empty or whitespace hostname, a hostname with no DNS records, or a malformed `host:port` value where to_socket_addrs() still succeeds but returns no addresses.","commonSituations":"A stale or misconfigured AP resolver endpoint returning empty hostnames; DNS misconfiguration (a record type exists but yields no A/AAAA results on the platform); IPv6-only or IPv4-only environments where the resolver filters out all addresses; corporate networks blocking DNS resolution of Spotify access points so the list contains unresolvable entries; a bug or version change upstream in how the AP list is fetched (resolve_ap/resolve_spclient) leaving blank strings in the list.","solutions":["Verify the access-point strings passed to `connect` are non-empty, valid `host:port` pairs (run `nslookup <host>` to confirm they resolve to at least one address).","Check DNS resolution on the machine (e.g. `dig <ap-host>`); fix resolv.conf/VPN/corporate DNS filtering if records are missing or filtered.","Confirm the AP resolve endpoint (AP_RESOLVE_ENDPOINT) is reachable and returning data; if resolution of the AP list itself failed, the list may contain garbage entries.","Try setting a SOCKS5 proxy_url so `stream_through_proxy` is used instead of direct resolution, bypassing local DNS.","Filter the ap_list before calling connect, dropping entries that fail `tokio::net::lookup_host` or std `to_socket_addrs`."],"exampleFix":"// before\nlet aps: Vec<String> = resolve_data.ap_list;\nConnection::connect(&aps, None)?\n\n// after\nlet aps: Vec<String> = resolve_data\n    .ap_list\n    .into_iter()\n    .filter(|ap| ap.to_socket_addrs().map(|mut a| a.next().is_some()).unwrap_or(false))\n    .collect();\nif aps.is_empty() {\n    return Err(Error::ConnectionFailed);\n}\nConnection::connect(&aps, None)?","handlingStrategy":"validation","validationCode":"fn ap_is_resolvable(ap: &str) -> bool {\n    use std::net::ToSocketAddrs;\n    ap.to_socket_addrs().map(|mut a| a.next().is_some()).unwrap_or(false)\n}\nlet aps: Vec<String> = ap_list.into_iter().filter(|ap| ap_is_resolvable(ap)).collect();\nassert!(!aps.is_empty(), \"no resolvable access points\");","typeGuard":"fn is_valid_ap(ap: &str) -> bool {\n    use std::net::ToSocketAddrs;\n    !ap.trim().is_empty()\n        && ap.to_socket_addrs().map(|mut it| it.next().is_some()).unwrap_or(false)\n}","tryCatchPattern":"match Connection::connect(&aps, None) {\n    Ok(conn) => conn,\n    Err(Error::ConnectionFailed) => {\n        // every AP failed; check DNS/network and retry or surface config problem\n        eprintln!(\"no access point reachable: verify DNS and AP list\");\n        return Err(Error::ConnectionFailed);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Validate every access-point string with to_socket_addrs before calling connect.","Check DNS health on the host (dig/nslookup) when deploying to containers, VPNs, or locked-down networks.","Log the AP list length and entries before connecting so empty/garbage entries are visible.","Prefer configuring a SOCKS5 proxy_url in environments where local DNS is unreliable.","Keep psst-core updated so the AP resolver endpoint and parsing stay correct."],"tags":["network","dns","tcp","resolution-failed"],"backgroundTag":"invalid-argument-value","analyzedSha":"3c3621aa79f820c737dd899e7e359b1359292466","analyzedAt":"2026-09-11T10:01:37.797Z","contentChangedAt":"2026-09-11T10:01:37.797Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}