copy/v86 · error · Error
pool of dynamic TCP port numbers exhausted, connection abort
Error message
pool of dynamic TCP port numbers exhausted, connection aborted
What it means
When opening an outbound TCP connection, the fake network stack allocates a dynamic source port by probing TCP_DYNAMIC_PORT_RANGE candidate ports for an unused ip:port:ip:port tuple. If all candidate tuples are already in use, no port can be allocated and the connection is aborted with this error.
Source
Thrown at src/browser/fake_network.js:1033
(spec.ipv4.dest[2] << 8 | spec.ipv4.dest[3]) +
IPV4_PROTO_TCP +
total_length;
view.setUint16(16, calc_inet_checksum(total_length, pseudo_header, view, out));
return total_length;
}
export function fake_tcp_connect(dport, adapter)
{
const vm_ip_str = adapter.vm_ip.join(".");
const router_ip_str = adapter.router_ip.join(".");
const sport_0 = (Math.random() * TCP_DYNAMIC_PORT_RANGE) | 0;
let sport, tuple, sport_i = 0;
do {
sport = TCP_DYNAMIC_PORT_START + ((sport_0 + sport_i) % TCP_DYNAMIC_PORT_RANGE);
tuple = `${vm_ip_str}:${dport}:${router_ip_str}:${sport}`;
} while(++sport_i < TCP_DYNAMIC_PORT_RANGE && adapter.tcp_conn[tuple]);
if(adapter.tcp_conn[tuple]) {
throw new Error("pool of dynamic TCP port numbers exhausted, connection aborted");
}
let conn = new TCPConnection(adapter);
conn.tuple = tuple;
conn.hsrc = adapter.router_mac;
conn.psrc = adapter.router_ip;
conn.sport = sport;
conn.hdest = adapter.vm_mac;
conn.dport = dport;
conn.pdest = adapter.vm_ip;
adapter.tcp_conn[tuple] = conn;
conn.connect();
return conn;
}
export function fake_tcp_probe(dport, adapter) {
return new Promise((res, rej) => {View on GitHub (pinned to 180830d539)
Solutions
- Close TCP connections that are no longer needed so their dynamic ports return to the pool (check for leaked/never-closed sockets)
- Increase TCP_DYNAMIC_PORT_START/TCP_DYNAMIC_PORT_RANGE constants to enlarge the ephemeral port pool
- Reduce the number of concurrent outbound connections from the guest and serialize heavy network work
- Add monitoring/logging of adapter.tcp_conn size to detect leaks early
Example fix
// before
conn = openTcp(dport); // throws after pool exhaustion
// after
try {
conn = openTcp(dport);
} catch (e) {
if (String(e.message).includes("dynamic TCP port")) {
closeIdleConnections();
conn = openTcp(dport); // retry after freeing ports
}
} Defensive patterns
Strategy: retry
Validate before calling
function portPoolUsage(adapter) {
return Object.keys(adapter.tcp_conn)
.filter(t => { const s = t.split(":")[3];
return s >= TCP_DYNAMIC_PORT_START && s < TCP_DYNAMIC_PORT_START + TCP_DYNAMIC_PORT_RANGE; }).length;
}
if (portPoolUsage(adapter) >= TCP_DYNAMIC_PORT_RANGE) freeIdleConnections(adapter); Try / catch
try {
conn = openOutboundTcp(adapter, dport);
} catch (e) {
if (e.message.includes("dynamic TCP port")) {
closeIdleTcpConnections(adapter);
conn = openOutboundTcp(adapter, dport); // retry once
} else throw e;
} Prevention
- Always close guest TCP connections when done; audit for leaked sockets
- Monitor adapter.tcp_conn size at runtime
- Keep TCP_DYNAMIC_PORT_RANGE at default ~64K or larger
- Serialize large parallel download workloads in the guest
When it happens
Trigger: Calling the outbound TCP connect path when all TCP_DYNAMIC_PORT_RANGE dynamic source ports for the VM IP are bound by existing connections in adapter.tcp_conn. Occurs after ~65535 (TCP_DYNAMIC_PORT_RANGE) simultaneously open connections, or if connections leak (never closed) until the pool wraps around.
Common situations: Long-running emulated sessions that open many sockets without closing them (leaked connections keep their tuples reserved); heavy parallel downloads from the emulated OS exhausting ephemeral ports; a regression that fails to delete tcp_conn entries on close.
Understand the failure class
- Connection failures: ECONNREFUSED, ECONNRESET, and friends — why connections get refused, reset, or dropped.
Related errors
- stream capacity overflow in GrowableRingbuffer.write(), pack
- Got a DATA packet but stream not registered. ID:
- Unknown port for localhost: "%s"
AI-assisted analysis of copy/v86@180830d539 (2026-08-31).
Data as JSON: /api/errors/502d0d1a25580b8a.
Report an issue: GitHub.