jpochyla/psst · error · io::Error
could not resolve to any addresses
Error message
could not resolve to any addresses
What it means
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.
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`.
Example fix
// before
let aps: Vec<String> = resolve_data.ap_list;
Connection::connect(&aps, None)?
// after
let aps: Vec<String> = resolve_data
.ap_list
.into_iter()
.filter(|ap| ap.to_socket_addrs().map(|mut a| a.next().is_some()).unwrap_or(false))
.collect();
if aps.is_empty() {
return Err(Error::ConnectionFailed);
}
Connection::connect(&aps, None)? Defensive patterns
Strategy: validation
Validate before calling
fn ap_is_resolvable(ap: &str) -> bool {
use std::net::ToSocketAddrs;
ap.to_socket_addrs().map(|mut a| a.next().is_some()).unwrap_or(false)
}
let aps: Vec<String> = ap_list.into_iter().filter(|ap| ap_is_resolvable(ap)).collect();
assert!(!aps.is_empty(), "no resolvable access points"); Type guard
fn is_valid_ap(ap: &str) -> bool {
use std::net::ToSocketAddrs;
!ap.trim().is_empty()
&& ap.to_socket_addrs().map(|mut it| it.next().is_some()).unwrap_or(false)
} Try / catch
match Connection::connect(&aps, None) {
Ok(conn) => conn,
Err(Error::ConnectionFailed) => {
// every AP failed; check DNS/network and retry or surface config problem
eprintln!("no access point reachable: verify DNS and AP list");
return Err(Error::ConnectionFailed);
}
Err(e) => return Err(e),
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
AI-assisted analysis of jpochyla/psst@3c3621aa79 (2026-09-11).
Data as JSON: /api/errors/a1555eb0e1d91124.
Report an issue: GitHub.
Appendix: source
Thrown at psst-core/src/connection/mod.rs:215
}
log::error!("failed to connect to any access point");
Err(Error::ConnectionFailed)
}
fn stream_without_proxy(ap: &str) -> Result<TcpStream, io::Error> {
let mut last_err = None;
for addr in ap.to_socket_addrs()? {
match TcpStream::connect_timeout(&addr, NET_CONNECT_TIMEOUT) {
Ok(stream) => {
return Ok(stream);
}
Err(err) => {
last_err.replace(err);
}
}
}
Err(last_err.unwrap_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
"could not resolve to any addresses",
)
}))
}
fn stream_through_proxy(ap: &str, url: &str) -> Result<TcpStream, Error> {
match Url::parse(url) {
Ok(url) if url.scheme() == "socks" || url.scheme() == "socks5" => {
// Currently we only support SOCKS5 proxies.
Self::stream_through_socks5_proxy(ap, &url)
}
_ => {
// Proxy URL failed to parse or has unsupported scheme.
Err(Error::ProxyUrlInvalid)
}
}
}View on GitHub (pinned to 3c3621aa79)