BeyondDimension/SteamTools · error · AggregateException
Unable to connect to {endPoint.Host}:{endPoint.Port}.
Error message
Unable to connect to {endPoint.Host}:{endPoint.Port}. What it means
Thrown by the TCP reverse-proxy handler when socket.ConnectAsync failed for every address tried for an endpoint. As with the other connect paths, each failure is appended to innerExceptions (with cancellation re-checked) and the final AggregateException names the target host:port.
Source
Thrown at src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Services.Implementation/HttpServer/TcpReverseProxyHandler.cs:62
var innerExceptions = new List<Exception>();
await foreach (var address in domainResolver.ResolveAsync(endPoint, cancellationToken))
{
var socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
using var timeoutTokenSource = new CancellationTokenSource(connectTimeout);
using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token);
await socket.ConnectAsync(address, endPoint.Port, linkedTokenSource.Token);
return new NetworkStream(socket, ownsSocket: false);
}
catch (Exception ex)
{
socket.Dispose();
cancellationToken.ThrowIfCancellationRequested();
innerExceptions.Add(ex);
}
}
throw new AggregateException(
$"Unable to connect to {endPoint.Host}:{endPoint.Port}.", innerExceptions);
}
}
#endifView on GitHub (pinned to c16ffa08e0)
Solutions
- Examine innerExceptions for the failure mode (refused vs timeout vs unreachable).
- Verify endPoint.Host:endPoint.Port is reachable directly from the host (telnet/Test-NetConnection).
- Check the reverse-proxy route/mapping table maps to the correct destination host and port.
- Confirm DNS/routing for the destination and that no firewall/ISP blocks the port.
Example fix
// before
throw new AggregateException(
$"Unable to connect to {endPoint.Host}:{endPoint.Port}.", innerExceptions);
// after: retry once with a fresh socket on transient failures before aggregating
var transient = innerExceptions.Any(e => e is SocketException or TimeoutException);
if (transient && attempt < maxAttempts) goto retry;
throw new AggregateException(
$"Unable to connect to {endPoint.Host}:{endPoint.Port} after {attempt} attempts.",
innerExceptions); Defensive patterns
Strategy: retry
Validate before calling
// Verify the destination endpoint before proxying.
async Task<bool> IsEndpointReachableAsync(EndPoint ep, CancellationToken ct)
{
using var s = new TcpClient();
using var cts = CancellationTokenSource.CreateLinkedTokenSource(ct);
cts.CancelAfter(connectTimeout);
try { await s.ConnectAsync(ep, cts.Token); return true; }
catch { return false; }
} Try / catch
try { await ProxyTcpAsync(endPoint, ct); }
catch (AggregateException ex) when (ex.Message.Contains("Unable to connect to"))
{
if (attempt < maxAttempts && ex.InnerExceptions.Any(e => e is SocketException or TimeoutException))
{ await Task.Delay(backoff, ct); goto retry; }
Log.Warning($"TCP upstream {endPoint.Host}:{endPoint.Port} unreachable: "
+ string.Join("; ", ex.InnerExceptions.Select(e => e.Message)));
throw;
} Prevention
- Keep the route table mapping destinations to known-good host:port pairs.
- Use a short connectTimeout and a bounded retry policy for transient failures.
- Health-check TCP destinations in the background and rotate away unhealthy ones.
- Distinguish timeout vs refused in logs to pinpoint firewall vs offline services.
When it happens
Trigger: Handling a TCP reverse-proxy request where connecting to endPoint.Host:endPoint.Port fails or times out for all resolved addresses within connectTimeout.
Common situations: Destination game/service host is down; firewall blocks the destination port; DNS returns private/unreachable IPs; the proxied TCP service moved or changed port; network path broken (VPN/route misconfiguration).
Related errors
- Could not find any IP that can be successfully connected.
- Unable to connect to {host}
- TCP port {httpProxyPort} is already occupied by other proces
- Failed to get available ports. There are no available ports.
AI-assisted analysis of BeyondDimension/SteamTools@c16ffa08e0 (2026-08-13).
Data as JSON: /api/errors/dc733fe414deb2af.
Report an issue: GitHub.