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);
    }
}
#endif

View on GitHub (pinned to c16ffa08e0)

Solutions

  1. Examine innerExceptions for the failure mode (refused vs timeout vs unreachable).
  2. Verify endPoint.Host:endPoint.Port is reachable directly from the host (telnet/Test-NetConnection).
  3. Check the reverse-proxy route/mapping table maps to the correct destination host and port.
  4. 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

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


AI-assisted analysis of BeyondDimension/SteamTools@c16ffa08e0 (2026-08-13). Data as JSON: /api/errors/dc733fe414deb2af. Report an issue: GitHub.