Skip to content

fix(download): disable uTP to prevent ENOBUFS socket exhaustion crashes - #185

Merged
baairon merged 1 commit into
baairon:mainfrom
kaiserc:fix/disable-utp-enobufs
Sep 6, 2026
Merged

fix(download): disable uTP to prevent ENOBUFS socket exhaustion crashes#185
baairon merged 1 commit into
baairon:mainfrom
kaiserc:fix/disable-utp-enobufs

Conversation

@kaiserc

@kaiserc kaiserc commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

What and why

WebTorrent's uTP transport implementation relies on the native \utp-native\ dependency. In \utp-native, each outgoing peer connection attempts to bind a new, independent UDP socket on an ephemeral port (
ew UTP()\ -> \uv_udp_bind(0, '0.0.0.0')) rather than multiplexing traffic over a single shared UDP socket.

Under active swarm discovery and peer reconnection churn, rapidly opening dozens to hundreds of UDP sockets exhausts the OS socket buffer space and dynamic port pool鈥攅specially on Windows, which triggers Winsock error 10055 (\WSAENOBUFS\ / \code: 'ENOBUFS', 'no buffer space available').

Furthermore, when \锟絠nding.utp_napi_bind\ throws \ENOBUFS, \utp-native\ schedules \process.nextTick(emitError, this, err)\ on the underlying \UTP\ socket instance. Because \UTP.connect\ only returns the connection stream (\conn) without attaching an error listener to the orphaned \UTP\ socket instance, this error is emitted with 0 listeners, escalating into an unhandled \uncaughtException\ that immediately terminates the process:
\
Error: no buffer space available
at UTP.bind (node_modules/utp-native/index.js:198:13)
at UTP.connect (node_modules/utp-native/index.js:165:27)
at UTP.connect (node_modules/utp-native/index.js:46:14)
at Torrent._drain (node_modules/webtorrent/lib/torrent.js:2110:23)
\\

This fix passes \utp: false\ to the \WebTorrent\ constructor options in \ensureClient(), forcing peer traffic over standard TCP (alongside the existing macOS NAT-PMP fix #22). Standard BitTorrent TCP (BEP 3) is supported by 100% of BitTorrent clients, fully error-handled, pooled, and immune to ephemeral UDP socket buffer exhaustion.

Checklist


  • pm run typecheck\ is clean

  • pm test\ passes
  • New logic has a test (vitest; mock node built-ins for platform code)
  • OS-touching code works on Windows, macOS, and Linux
  • One concern, with a Conventional Commits title (\ eat:\ / \ ix:\ / \docs:\ / \chore:)

WebTorrent's uTP transport uses utp-native, which allocates an independent UDP socket for every outgoing peer connection attempt. Under heavy swarm discovery and peer reconnection churn, Windows rapidly exhausts socket buffer space and dynamic ports (WSAENOBUFS / ENOBUFS: 'no buffer space available').

Furthermore, when binding fails with ENOBUFS, utp-native's UTP.connect emits an 'error' event on an orphaned EventEmitter that has no error listener registered, triggering an unhandled exception that crashes the entire application.

Disabling uTP via { utp: false } instructs WebTorrent to connect to peers exclusively via standard TCP. TCP connections are universally supported by all BitTorrent clients, fully error-handled, pooled, and do not exhaust ephemeral UDP socket buffers.
@baairon
baairon merged commit 353c332 into baairon:main Sep 6, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

macOS: Download crashes with EADDRINUSE on UDP port 5350

2 participants