{"record":{"id":"af51989e35810e3b","repo":"vllm-project/vllm","slug":"lock-must-be-provided-for-readers","errorCode":null,"errorMessage":"Lock must be provided for readers.","messagePattern":"Lock must be provided for readers\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"vllm/distributed/device_communicators/shm_object_storage.py","lineNumber":492,"sourceCode":"        self.max_object_size = max_object_size\n        self.n_readers = n_readers\n        self.serde_class = serde_class\n        self.ser_de = serde_class()\n        self.ring_buffer = ring_buffer\n        self.is_writer = self.ring_buffer.is_writer\n\n        self.flag_bytes = 4  # for in-use flag\n\n        if self.is_writer:\n            # Key-value mapping: key -> (address, monotonic_id)\n            self.key_index: dict[str, tuple[int, int]] = {}\n            # Reverse mapping: monotonic_id -> key\n            self.id_index: dict[int, str] = {}\n            # Writer flag to track in-use status: monotonic_id -> count\n            self.writer_flag: dict[int, int] = {}\n        else:\n            if reader_lock is None:\n                raise ValueError(\"Lock must be provided for readers.\")\n\n        self._reader_lock = reader_lock\n\n    def clear(self) -> None:\n        \"\"\"Clear the object storage.\"\"\"\n        if self.is_writer:\n            self.ring_buffer.clear()\n            self.key_index.clear()\n            self.id_index.clear()\n            self.writer_flag.clear()\n            logger.debug(\"Object storage cleared and reinitialized.\")\n\n    def copy_to_buffer(\n        self,\n        data: bytes | list[bytes],\n        data_bytes: int,\n        metadata: bytes,\n        md_bytes: int,","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/vllm-project/vllm/blob/c794754062d49a8fdb63ab3c5215b488b865030c/vllm/distributed/device_communicators/shm_object_storage.py#L474-L510","documentation":"ShmObjectStorage requires a reader_lock for any instance constructed with is_writer=False. Readers must coordinate increments of the per-buffer in-use flag via a cross-process lock; without it the constructor refuses to build a half-initialized reader.","triggerScenarios":"Instantiating ShmObjectStorage(..., is_writer=False, reader_lock=None) — e.g. building a reader from a handle but forgetting to pass the lock stored in ShmObjectStorageHandle.reader_lock.","commonSituations":"Custom code creating reader-side storage from a serialized handle (the handle carries reader_lock; developers drop it when the lock type is not picklable across their spawn method); refactors that changed the constructor signature to make the lock mandatory.","solutions":["Pass the lock from the handle: ShmObjectStorage(..., reader_lock=handle.reader_lock)","If spawning readers via pickle/spawn and the lock cannot cross the boundary, create the lock in the reader process from the same shm/semaphore name rather than passing None","Check is_writer is set correctly — writer instances legitimately pass reader_lock=None"],"exampleFix":"# before\nstorage = ShmObjectStorage(..., is_writer=False, reader_lock=None)\n# ValueError: Lock must be provided for readers.\n\n# after\nstorage = ShmObjectStorage(..., is_writer=False, reader_lock=handle.reader_lock)","handlingStrategy":"validation","validationCode":"# when building a reader from a handle\nif not handle_is_writer:\n    assert handle.reader_lock is not None, \"reader_lock missing from handle\"","typeGuard":"def is_valid_reader_config(is_writer: bool, reader_lock) -> bool:\n    return is_writer or reader_lock is not None","tryCatchPattern":null,"preventionTips":["Always transport ShmObjectStorageHandle as a whole (it carries reader_lock)","Construct readers via the provided handle/from_handle API instead of manual kwargs","Add a constructor unit test covering reader-without-lock"],"tags":["configuration","api-misuse","shared-memory"],"backgroundTag":null,"analyzedSha":"c794754062d49a8fdb63ab3c5215b488b865030c","analyzedAt":"2026-08-14T21:17:39.825Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}