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()
@staticmethodView on GitHub (pinned to c794754062)
Solutions
- 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
- If you need to consume on this process, construct MessageQueue with this rank included in local_reader_ranks (or connect via remote_reader)
- 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
- Register consumer ranks as local_reader_ranks/remote readers at MessageQueue construction
- Only the broadcaster calls broadcast_object(); only reader ranks call dequeue()
- Assert the reader flags before entering a dequeue loop in multi-process scaffolding
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
- Insufficient space in {shm_path}: {required_bytes / mib:.0f}
- Not enough space in the data buffer, try calling free_buf()
- Lock must be provided for readers.
- Key '{key}' already exists in the storage.
- tool response messages require a tool_call_id; use ChatMessa
AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14).
Data as JSON: /api/errors/b213d31a60f50b16.
Report an issue: GitHub.