BornToBeRoot/NETworkManager · error · Exception
Error while retrieving TCP table
Error message
Error while retrieving TCP table
What it means
GetActiveTcpConnections calls the Win32 GetExtendedTcpTable API (TCP_TABLE_OWNER_PID_ALL). If the native call returns a non-zero result code (e.g. ERROR_INSUFFICIENT_BUFFER because the table grew, or ERROR_NO_DATA / access issues), the method throws a bare Exception('Error while retrieving TCP table') without exposing the underlying Win32 error code.
Solutions
- Retry GetActiveTcpConnections; the transient size race usually resolves on the next call.
- Check the last Win32 error (Marshal.GetLastWin32Error) around the native call for the specific cause.
- Increase the initial buffer size or loop with a larger allocation before giving up.
- Catch the exception and degrade gracefully (show an empty/unknown connection list) instead of crashing.
Example fix
// before
dwResult = GetExtendedTcpTable(tcpTable, ref size, false, 2, TcpTableClass.TCP_TABLE_OWNER_PID_ALL, 0);
if (dwResult != 0)
throw new Exception("Error while retrieving TCP table");
// after
dwResult = GetExtendedTcpTable(tcpTable, ref size, false, 2, TcpTableClass.TCP_TABLE_OWNER_PID_ALL, 0);
if (dwResult != 0)
throw new Win32Exception((int)dwResult, $"Error while retrieving TCP table (0x{(uint)dwResult:X})"); Defensive patterns
Strategy: retry
Validate before calling
// cannot pre-validate the native table; check environment instead // ensure there is at least one active TCP-capable interface bool hasNetwork = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
Type guard
null
Try / catch
try
{
var conns = Connection.GetActiveTcpConnections();
}
catch (Exception ex) when (ex.Message == "Error while retrieving TCP table")
{
Log.Warn("TCP table unavailable, retrying once...", ex);
await Task.Delay(100);
// retry or degrade to empty list
} Prevention
- Retry once on failure; the buffer-size race is transient.
- Surface Marshal.GetLastWin32Error for diagnostics when the throw happens.
- Never hard-crash the UI for snapshot APIs; degrade to 'unknown'.
When it happens
Trigger: Calling GetActiveTcpConnections when the retry loop with the fixed initial buffer cannot satisfy GetExtendedTcpTable (table changed between size query and call), the buffer cannot be allocated, or the API returns ERROR_NO_DATA because there are no TCP connections.
Common situations: Rapid connection churn on busy systems causing the size race; systems with very large TCP tables; restricted environments where the API is denied; calling during heavy network changes.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- Win32Exception for native error code (int)result
- string.Join("; ", ps.Streams.Error)
- message (joined PowerShell error streams)
- string.Join("; ", ps.Streams.Error.Select(e =>…
- Active Directory search failed for
AI-assisted analysis of BornToBeRoot/NETworkManager@2780d65469 (2026-09-12).
Data as JSON: /api/errors/c7c12f5ca301db0c.
Report an issue: GitHub.
Appendix: source
Thrown at Source/NETworkManager.Models/Network/Connection.cs:87
return Task.Run(GetActiveTcpConnections);
}
private static List<ConnectionInfo> GetActiveTcpConnections()
{
var result = new List<ConnectionInfo>();
var size = 0;
// ReSharper disable once RedundantAssignment - size is get by reference
var dwResult = GetExtendedTcpTable(IntPtr.Zero, ref size, false, 2, TcpTableClass.TCP_TABLE_OWNER_PID_ALL, 0);
var tcpTable = Marshal.AllocHGlobal(size);
try
{
dwResult = GetExtendedTcpTable(tcpTable, ref size, false, 2, TcpTableClass.TCP_TABLE_OWNER_PID_ALL, 0);
if (dwResult != 0)
throw new Exception("Error while retrieving TCP table");
var tableRows = Marshal.ReadInt32(tcpTable);
var rowPtr = tcpTable + 4;
for (var i = 0; i < tableRows; i++)
{
var row = (MibTcpRowOwnerPid)Marshal.PtrToStructure(rowPtr, typeof(MibTcpRowOwnerPid))!;
var localAddress = new IPAddress(row.localAddr);
var localPort = BitConverter.ToUInt16([row.localPort2, row.localPort1], 0);
var remoteAddress = new IPAddress(row.remoteAddr);
var remotePort = BitConverter.ToUInt16([row.remotePort2, row.remotePort1], 0);
var state = (TcpState)row.state;
// Get process info by PID
var processId = (int)row.owningPid;
var processName = "-/-";
var processPath = "-/-";View on GitHub (pinned to 2780d65469)