denoland/deno · error

UDP socket IPC handle passing is not supported on this platf

Error message

UDP socket IPC handle passing is not supported on this platform

What it means

Deno's node-compat op that adopts a UDP socket received over the Node IPC channel (fd passed from a parent process, e.g. via cluster or child_process) is only implemented for Unix. The #[cfg(not(unix))] branch returns ErrorKind::Unsupported with this message, so on Windows a bound UDP socket cannot be handed to a child through IPC.

Source

Thrown at ext/node/ops/udp.rs:694

  #[cfg(unix)]
  {
    use std::os::unix::io::FromRawFd;
    // SAFETY: The fd was received via SCM_RIGHTS and is a valid, open socket.
    let std_socket = unsafe { std::net::UdpSocket::from_raw_fd(fd) };
    std_socket.set_nonblocking(true)?;
    let local_addr = std_socket.local_addr()?;
    let socket = UdpSocket::from_std(std_socket)?;
    let resource = NodeUdpSocketResource {
      socket,
      cancel: Default::default(),
    };
    let rid = state.resource_table.add(resource);
    Ok((rid, local_addr.ip().to_string(), local_addr.port()))
  }
  #[cfg(not(unix))]
  {
    let _ = (state, fd);
    Err(NodeUdpError::Io(std::io::Error::new(
      std::io::ErrorKind::Unsupported,
      "UDP socket IPC handle passing is not supported on this platform",
    )))
  }
}

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Do not pass UDP sockets over IPC on Windows; bind a fresh socket in the child and send only configuration (port, multicast membership) over the channel.
  2. Gate the feature: if (process.platform === 'win32') use a fallback path that creates the socket in each worker with SO_REUSEADDR.
  3. Run the workload in a Linux container when the handle-passing behavior is required.

Example fix

// before (primary)
worker.send({ cmd: 'bind' }, udpSocket); // fails on Windows: UDP socket IPC handle passing is not supported

// after
if (process.platform === 'win32') {
  worker.send({ cmd: 'bind', port: 54321 }); // child binds its own socket
} else {
  worker.send({ cmd: 'bind' }, udpSocket);
}
Defensive patterns

Strategy: validation

Validate before calling

const canPassUdpOverIpc = process.platform !== "win32";
if (!canPassUdpOverIpc) worker.send({ cmd: "bind", port }); else worker.send({ cmd: "bind" }, udpSocket);

Type guard

const supportsUdpIpc = (p: NodeJS.Platform): p is "linux" | "darwin" | "freebsd" => p !== "win32";

Try / catch

try { child.send(msg, udpSocket); } catch (e) { if (/not supported on this platform/.test(String(e))) child.send({ ...msg, bindYourself: true }); else throw e; }

Prevention

When it happens

Trigger: Using node:cluster on Windows where the primary passes a dgram socket to a worker, or child_process with an IPC channel that tries to transfer a UDP socket handle to the child on Windows. The op receives the fd over the channel and immediately fails because handle adoption is Unix-only.

Common situations: Code that works on Linux/macOS CI fails when run or deployed on Windows; cross-platform test matrices; npm packages that rely on cluster+dgram (e.g. some metric collectors).

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/46f7daf07aaf4e96. Report an issue: GitHub.