BeyondDimension/SteamTools · error · ApplicationException

Failed to get available ports. There are no available ports.

Error message

Failed to get available ports. There are no available ports.

What it means

Thrown by GetAvailablePort after scanning every port from minPort up to IPEndPoint.MaxPort (65535) without finding one that satisfies the availability predicate (TCP-only, UDP-only, or TCP+UDP). It indicates total port exhaustion across the scanned range rather than a single collision.

Source

Thrown at src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/Abstractions/IReverseProxyConfig.GlobalListener.cs:114

    public static int GetAvailableUdpPort(int minPort) => GetAvailablePort(IsAvailableUdp, minPort);

    /// <summary>
    /// 获取一个随机的可用的 TCP 和 UDP 端口 
    /// </summary>
    /// <param name="minPort"></param>
    /// <returns></returns>
    public static int GetAvailableTcpAndUdpPort(int minPort) => GetAvailablePort(IsAvailableTcpAndUdp, minPort);

    static int GetAvailablePort(Func<int, bool> isAvailable, int minPort)
    {
        for (var port = minPort; port < IPEndPoint.MaxPort; port++)
        {
            if (isAvailable(port) == true)
            {
                return port;
            }
        }
        throw new ApplicationException("Failed to get available ports. There are no available ports.");
    }
}

View on GitHub (pinned to c16ffa08e0)

Solutions

  1. Lower minPort in the reverse-proxy config so the scan covers a wider range.
  2. Identify and close the process/socket leak consuming ports (check open handle counts and TIME_WAIT sockets).
  3. Increase the dynamic port range / reduce TIME_WAIT retention at the OS level, then retry.
  4. Restart the host to release leaked sockets if a process leak is confirmed.

Example fix

// before: tiny scan window
var port = IReverseProxyConfig.GetAvailableTcpAndUdpPort(minPort: 65000);

// after: reasonable scan window
var port = IReverseProxyConfig.GetAvailableTcpAndUdpPort(minPort: 10000);
Defensive patterns

Strategy: validation

Validate before calling

// Sanity-check minPort before scanning so the range is not uselessly small.
if (minPort < IPEndPoint.MinPort || minPort > IPEndPoint.MaxPort - 1024)
    throw new ArgumentOutOfRangeException(nameof(minPort), "minPort leaves too small a scan window.");

// Optionally check system ephemeral-port health before requesting a port.
var used = QueryCurrentOpenPortCount();
if (used > 50000) throw new InvalidOperationException("System near port exhaustion; free sockets first.");

Try / catch

try { return IReverseProxyConfig.GetAvailableTcpAndUdpPort(minPort); }
catch (ApplicationException ex) when (ex.Message.Contains("no available ports"))
{
    Log.Error("Port exhaustion in range. Consider lowering minPort or restarting the host.");
    throw;
}

Prevention

When it happens

Trigger: Calling GetAvailableTcpPort/GetAvailableUdpPort/GetAvailableTcpAndUdpPort with a minPort so high, or a system so loaded, that no port in [minPort, 65535] passes the isAvailable check.

Common situations: minPort is misconfigured to a value near 65535 leaving almost no scan range; ephemeral port exhaustion from many short-lived connections has consumed the dynamic range; a leak keeps opening sockets without closing them; security software reserves wide port ranges.

Related errors


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