{"record":{"id":"e119ec6a5553d6b6","repo":"sgl-project/sglang","slug":"expected-one-fd-got-len-fds","errorCode":null,"errorMessage":"expected one fd, got {len(fds)}","messagePattern":"expected one fd, got (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/weight_cache/transport.py","lineNumber":55,"sourceCode":"\ndef _recv_fd(sock: socket.socket) -> Tuple[int, int]:\n    fd_item_size = array.array(\"i\").itemsize\n    data, ancdata, _, _ = sock.recvmsg(\n        _FD_INDEX_STRUCT.size, socket.CMSG_SPACE(fd_item_size)\n    )\n    if len(data) != _FD_INDEX_STRUCT.size:\n        raise RuntimeError(\n            f\"received truncated fd header: {len(data)} < {_FD_INDEX_STRUCT.size}\"\n        )\n    index = _FD_INDEX_STRUCT.unpack(data)[0]\n    fds = array.array(\"i\")\n    for level, cmsg_type, cmsg_data in ancdata:\n        if level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS:\n            fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fd_item_size)])\n    if len(fds) != 1:\n        for fd in fds:\n            os.close(fd)\n        raise RuntimeError(f\"expected one fd, got {len(fds)}\")\n    return int(index), int(fds[0])\n\n\nclass WeightCacheTransportBackend(ABC):\n    name: str\n\n    @abstractmethod\n    def prepare_export(\n        self, state_tensors: Mapping[str, Tuple[torch.Tensor, bool]]\n    ) -> Dict[str, Dict[str, Any]]:\n        \"\"\"Prepare daemon-side entries for all tensors.\"\"\"\n\n    @abstractmethod\n    def send_fetch_state_response(\n        self,\n        conn: socket.socket,\n        *,\n        config: Dict[str, Any],","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/weight_cache/transport.py#L37-L73","documentation":"_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.","triggerScenarios":"Peer packs multiple FDs into one sendmsg; ancillary data corrupted or coalesced unexpectedly.","commonSituations":"Protocol implementation mismatch; a buggy or adversarial peer on the unix socket.","solutions":["Ensure both sides use the same sglang transport implementation (one FD per message)","Restart daemon/client; if persistent, capture a repro and report upstream"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    idx, fd = _recv_fd(sock)\nexcept RuntimeError as e:\n    if 'expected one fd' in str(e): abort_transport()","preventionTips":["Send exactly one FD per sendmsg","Validate peer implementation before FD exchange"],"tags":["ipc","fd-passing","protocol"],"backgroundTag":"unexpected-fd-count","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}