vllm-project/vllm · error · RuntimeError

Only readers can dequeue

Error message

Only readers can dequeue

What it means

MessageQueue.dequeue() only pulls objects from the shared-memory/ZMQ broadcast channel on processes registered as readers. The queue instance checks _is_local_reader and _is_remote_reader; when both are false the process is the writer (or was never registered as a reader), so there is nothing to dequeue and vLLM raises RuntimeError instead of blocking or returning garbage.

Source

Thrown at vllm/distributed/device_communicators/shm_broadcast.py:906

        if self._is_local_reader:
            with self.acquire_read(timeout, indefinite) as buf:
                overflow = buf[0] == 1
                if not overflow:
                    offset = 3
                    buf_count = from_bytes_big(buf[1:offset])
                    all_buffers = []
                    for i in range(buf_count):
                        buf_offset = offset + 4
                        buf_len = from_bytes_big(buf[offset:buf_offset])
                        offset = buf_offset + buf_len
                        all_buffers.append(buf[buf_offset:offset])
                    obj = pickle.loads(all_buffers[0], buffers=all_buffers[1:])
            if overflow:
                obj = MessageQueue.recv(self.local_socket, timeout)
        elif self._is_remote_reader:
            obj = MessageQueue.recv(self.remote_socket, timeout)
        else:
            raise RuntimeError("Only readers can dequeue")
        return obj

    @staticmethod
    def recv(socket: zmq.Socket, timeout: float | None) -> Any:
        # Ensure non-negative timeout passed to zmq poll.
        timeout_ms = None if timeout is None else max(0, int(timeout * 1000))
        if not socket.poll(timeout=timeout_ms):
            raise TimeoutError
        recv, *recv_oob = socket.recv_multipart(copy=False)
        return pickle.loads(recv, buffers=recv_oob)

    def broadcast_object(self, obj=None):
        if self._is_writer:
            self.enqueue(obj)
            return obj
        return self.dequeue()

    @staticmethod

View on GitHub (pinned to c794754062)

Solutions

  1. Verify which process owns the object: only the ranks passed as readers at construction may call dequeue(); the creator/writer must call broadcast_object() instead
  2. If you need to consume on this process, construct MessageQueue with this rank included in local_reader_ranks (or connect via remote_reader)
  3. If you meant to send, call broadcast_object(obj) rather than dequeue()

Example fix

# before
mq = MessageQueue(..., local_reader_ranks=[])
obj = mq.dequeue()  # RuntimeError: Only readers can dequeue

# after (writer side)
mq = MessageQueue(..., local_reader_ranks=[1, 2])
mq.broadcast_object(obj)  # this process writes, ranks 1-2 dequeue()
Defensive patterns

Strategy: validation

Validate before calling

# before dequeue, assert this instance is a reader
assert mq._is_local_reader or mq._is_remote_reader, (
    "dequeue() is reader-only; this process is the writer"
)

Type guard

def can_dequeue(mq: "MessageQueue") -> bool:
    return bool(getattr(mq, "_is_local_reader", False) or getattr(mq, "_is_remote_reader", False))

Prevention

When it happens

Trigger: Calling msg_queue.dequeue(timeout=...) on the process that created the MessageQueue in writer mode, or constructing a queue with reader_rank=None/local_reader_ranks=[] and then calling dequeue(). Also happens if a helper process re-imports and rebuilds the broadcast object instead of receiving the reader end.

Common situations: Custom multiprocessing code around vLLM's shm_broadcast (e.g. collecting logs/outputs from workers) where the developer calls dequeue() on the broadcaster; version changes that altered reader registration arguments in MessageQueue.__init__.

Related errors


AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14). Data as JSON: /api/errors/b213d31a60f50b16. Report an issue: GitHub.