{"record":{"id":"e914e78548b3944b","repo":"BeyondDimension/SteamTools","slug":"failed-to-get-available-ports-there-are-no-availa","errorCode":null,"errorMessage":"Failed to get available ports. There are no available ports.","messagePattern":"Failed to get available ports\\. There are no available ports\\.","errorType":"exception","errorClass":"ApplicationException","httpStatus":null,"severity":"error","filePath":"src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/Abstractions/IReverseProxyConfig.GlobalListener.cs","lineNumber":114,"sourceCode":"    public static int GetAvailableUdpPort(int minPort) => GetAvailablePort(IsAvailableUdp, minPort);\n\n    /// <summary>\n    /// 获取一个随机的可用的 TCP 和 UDP 端口 \n    /// </summary>\n    /// <param name=\"minPort\"></param>\n    /// <returns></returns>\n    public static int GetAvailableTcpAndUdpPort(int minPort) => GetAvailablePort(IsAvailableTcpAndUdp, minPort);\n\n    static int GetAvailablePort(Func<int, bool> isAvailable, int minPort)\n    {\n        for (var port = minPort; port < IPEndPoint.MaxPort; port++)\n        {\n            if (isAvailable(port) == true)\n            {\n                return port;\n            }\n        }\n        throw new ApplicationException(\"Failed to get available ports. There are no available ports.\");\n    }\n}","sourceCodeStart":96,"sourceCodeEnd":116,"githubUrl":"https://github.com/BeyondDimension/SteamTools/blob/c16ffa08e03b192d23ada290c4969e77f9201f3d/src/BD.WTTS.Client.Plugins.Accelerator.ReverseProxy/Models/Abstractions/IReverseProxyConfig.GlobalListener.cs#L96-L116","documentation":"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.","triggerScenarios":"Calling GetAvailableTcpPort/GetAvailableUdpPort/GetAvailableTcpAndUdpPort with a minPort so high, or a system so loaded, that no port in [minPort, 65535] passes the isAvailable check.","commonSituations":"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.","solutions":["Lower minPort in the reverse-proxy config so the scan covers a wider range.","Identify and close the process/socket leak consuming ports (check open handle counts and TIME_WAIT sockets).","Increase the dynamic port range / reduce TIME_WAIT retention at the OS level, then retry.","Restart the host to release leaked sockets if a process leak is confirmed."],"exampleFix":"// before: tiny scan window\nvar port = IReverseProxyConfig.GetAvailableTcpAndUdpPort(minPort: 65000);\n\n// after: reasonable scan window\nvar port = IReverseProxyConfig.GetAvailableTcpAndUdpPort(minPort: 10000);","handlingStrategy":"validation","validationCode":"// Sanity-check minPort before scanning so the range is not uselessly small.\nif (minPort < IPEndPoint.MinPort || minPort > IPEndPoint.MaxPort - 1024)\n    throw new ArgumentOutOfRangeException(nameof(minPort), \"minPort leaves too small a scan window.\");\n\n// Optionally check system ephemeral-port health before requesting a port.\nvar used = QueryCurrentOpenPortCount();\nif (used > 50000) throw new InvalidOperationException(\"System near port exhaustion; free sockets first.\");","typeGuard":null,"tryCatchPattern":"try { return IReverseProxyConfig.GetAvailableTcpAndUdpPort(minPort); }\ncatch (ApplicationException ex) when (ex.Message.Contains(\"no available ports\"))\n{\n    Log.Error(\"Port exhaustion in range. Consider lowering minPort or restarting the host.\");\n    throw;\n}","preventionTips":["Set minPort to a sensible default (e.g. 10000) so the scan has a large window.","Monitor open socket / TIME_WAIT counts and alert before exhaustion.","Fix socket leaks (always Dispose sockets/HttpClients; avoid creating per-request clients).","Tune the OS dynamic port range and TIME_WAIT timeout on hosts running the proxy."],"tags":["network","port","resource-exhaustion","configuration"],"backgroundTag":null,"analyzedSha":"c16ffa08e03b192d23ada290c4969e77f9201f3d","analyzedAt":"2026-08-13T11:52:20.410Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}