{"record":{"id":"502d0d1a25580b8a","repo":"copy/v86","slug":"pool-of-dynamic-tcp-port-numbers-exhausted-connec","errorCode":null,"errorMessage":"pool of dynamic TCP port numbers exhausted, connection aborted","messagePattern":"pool of dynamic TCP port numbers exhausted, connection aborted","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/browser/fake_network.js","lineNumber":1033,"sourceCode":"        (spec.ipv4.dest[2] << 8 | spec.ipv4.dest[3]) +\n        IPV4_PROTO_TCP +\n        total_length;\n    view.setUint16(16, calc_inet_checksum(total_length, pseudo_header, view, out));\n    return total_length;\n}\n\nexport function fake_tcp_connect(dport, adapter)\n{\n    const vm_ip_str = adapter.vm_ip.join(\".\");\n    const router_ip_str = adapter.router_ip.join(\".\");\n    const sport_0 = (Math.random() * TCP_DYNAMIC_PORT_RANGE) | 0;\n    let sport, tuple, sport_i = 0;\n    do {\n        sport = TCP_DYNAMIC_PORT_START + ((sport_0 + sport_i) % TCP_DYNAMIC_PORT_RANGE);\n        tuple = `${vm_ip_str}:${dport}:${router_ip_str}:${sport}`;\n    } while(++sport_i < TCP_DYNAMIC_PORT_RANGE && adapter.tcp_conn[tuple]);\n    if(adapter.tcp_conn[tuple]) {\n        throw new Error(\"pool of dynamic TCP port numbers exhausted, connection aborted\");\n    }\n\n    let conn = new TCPConnection(adapter);\n\n    conn.tuple = tuple;\n    conn.hsrc = adapter.router_mac;\n    conn.psrc = adapter.router_ip;\n    conn.sport = sport;\n    conn.hdest = adapter.vm_mac;\n    conn.dport = dport;\n    conn.pdest = adapter.vm_ip;\n    adapter.tcp_conn[tuple] = conn;\n    conn.connect();\n    return conn;\n}\n\nexport function fake_tcp_probe(dport, adapter) {\n    return new Promise((res, rej) => {","sourceCodeStart":1015,"sourceCodeEnd":1051,"githubUrl":"https://github.com/copy/v86/blob/180830d539dcc87db1a191febf6c914f516d102f/src/browser/fake_network.js#L1015-L1051","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconn = openTcp(dport); // throws after pool exhaustion\n// after\ntry {\n    conn = openTcp(dport);\n} catch (e) {\n    if (String(e.message).includes(\"dynamic TCP port\")) {\n    closeIdleConnections();\n    conn = openTcp(dport); // retry after freeing ports\n    }\n}","handlingStrategy":"retry","validationCode":"function portPoolUsage(adapter) {\n    return Object.keys(adapter.tcp_conn)\n    .filter(t => { const s = t.split(\":\")[3];\n        return s >= TCP_DYNAMIC_PORT_START && s < TCP_DYNAMIC_PORT_START + TCP_DYNAMIC_PORT_RANGE; }).length;\n}\nif (portPoolUsage(adapter) >= TCP_DYNAMIC_PORT_RANGE) freeIdleConnections(adapter);","typeGuard":null,"tryCatchPattern":"try {\n    conn = openOutboundTcp(adapter, dport);\n} catch (e) {\n    if (e.message.includes(\"dynamic TCP port\")) {\n    closeIdleTcpConnections(adapter);\n    conn = openOutboundTcp(adapter, dport); // retry once\n    } else throw e;\n}","preventionTips":["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"],"tags":["network","tcp","ports","resource-exhaustion"],"backgroundTag":"ephemeral-port-exhaustion","analyzedSha":"180830d539dcc87db1a191febf6c914f516d102f","analyzedAt":"2026-08-31T22:39:37.599Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}