sgl-project/sglang · error · RuntimeError

expected one fd, got {len(fds)}

Error message

expected one fd, got {len(fds)}

What it means

_recv_fd received a SCM_RIGHTS control message carrying zero or multiple file descriptors, but the protocol carries exactly one FD per message. Extra FDs are closed and the error raised to prevent descriptor leaks.

Source

Thrown at python/sglang/srt/weight_cache/transport.py:55

def _recv_fd(sock: socket.socket) -> Tuple[int, int]:
    fd_item_size = array.array("i").itemsize
    data, ancdata, _, _ = sock.recvmsg(
        _FD_INDEX_STRUCT.size, socket.CMSG_SPACE(fd_item_size)
    )
    if len(data) != _FD_INDEX_STRUCT.size:
        raise RuntimeError(
            f"received truncated fd header: {len(data)} < {_FD_INDEX_STRUCT.size}"
        )
    index = _FD_INDEX_STRUCT.unpack(data)[0]
    fds = array.array("i")
    for level, cmsg_type, cmsg_data in ancdata:
        if level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS:
            fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fd_item_size)])
    if len(fds) != 1:
        for fd in fds:
            os.close(fd)
        raise RuntimeError(f"expected one fd, got {len(fds)}")
    return int(index), int(fds[0])


class WeightCacheTransportBackend(ABC):
    name: str

    @abstractmethod
    def prepare_export(
        self, state_tensors: Mapping[str, Tuple[torch.Tensor, bool]]
    ) -> Dict[str, Dict[str, Any]]:
        """Prepare daemon-side entries for all tensors."""

    @abstractmethod
    def send_fetch_state_response(
        self,
        conn: socket.socket,
        *,
        config: Dict[str, Any],

View on GitHub (pinned to 0132848349)

Solutions

  1. Ensure both sides use the same sglang transport implementation (one FD per message)
  2. Restart daemon/client; if persistent, capture a repro and report upstream
Defensive patterns

Strategy: try-catch

Try / catch

try:
    idx, fd = _recv_fd(sock)
except RuntimeError as e:
    if 'expected one fd' in str(e): abort_transport()

Prevention

When it happens

Trigger: Peer packs multiple FDs into one sendmsg; ancillary data corrupted or coalesced unexpectedly.

Common situations: Protocol implementation mismatch; a buggy or adversarial peer on the unix socket.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/e119ec6a5553d6b6. Report an issue: GitHub.