{"record":{"id":"59ce02265921f617","repo":"sgl-project/sglang","slug":"hf3fsclient-check-offsets-sizes","errorCode":null,"errorMessage":"Hf3fsClient.check: {offsets=}, {sizes=}","messagePattern":"Hf3fsClient\\.check: (.+?), (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/mem_cache/storage/hf3fs/hf3fs_usrbio_client.py","lineNumber":204,"sourceCode":"        return results\n\n    def check(self, offsets: List[int], tensors: List[torch.Tensor]) -> None:\n        sizes = [t.numel() * t.itemsize for t in tensors]\n        if any(\n            [\n                len(offsets) > self.entries,\n                len(offsets) != len(sizes),\n                all(\n                    [\n                        offset < 0 or offset + size > self.size\n                        for offset, size in zip(offsets, sizes)\n                    ]\n                ),\n                all([size > self.bytes_per_page for size in sizes]),\n            ]\n        ):\n            self.close()\n            raise ValueError(f\"Hf3fsClient.check: {offsets=}, {sizes=}\")\n\n    def get_size(self) -> int:\n        return self.size\n\n    def close(self) -> None:\n        deregister_fd(self.file)\n        os.close(self.file)\n        del self.ior_r\n        del self.ior_w\n        del self.iov_r\n        del self.iov_w\n        self.shm_r.close()\n        self.shm_w.close()\n\n    def flush(self) -> None:\n        os.fsync(self.file)\n","sourceCodeStart":186,"sourceCodeEnd":221,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/mem_cache/storage/hf3fs/hf3fs_usrbio_client.py#L186-L221","documentation":"check() validates batch_read/batch_write inputs: offsets must be page-aligned/monotonic (implied by the sorted offsets condition) and every size must exceed bytes_per_page. On violation it closes the client and raises ValueError echoing the offending offsets and sizes, because the usrbio batch API cannot express such requests.","triggerScenarios":"Calling batch_read/batch_write with unaligned or non-monotonic offsets, or with a size <= bytes_per_page (e.g. a single-token partial page read). The client is closed, so subsequent calls fail too.","commonSituations":"Caller computing offsets from token slot indices without multiplying by page size; mixing page-sized and sub-page reads in one batch after a config change to bytes_per_page; sorting bug producing non-monotonic offsets.","solutions":["Check the echoed {offsets=}/{sizes=} — non-multiples of bytes_per_page mean your index math dropped the page-size multiply","Coalesce reads so each entry is a full page (size > bytes_per_page) or route small reads through a non-batched path","Note the client is closed by check(): recreate the client after fixing inputs instead of reusing it"],"exampleFix":"# before\noffs = [slot for slot in slots]  # slot indices, not byte offsets\nclient.batch_read(offs, sizes)\n\n# after\noffs = [slot * bytes_per_page for slot in slots]\nsizes = [bytes_per_page * n_pages for n_pages in page_counts]\nclient.batch_read(offs, sizes)","handlingStrategy":"validation","validationCode":"def valid_batch(offsets: list[int], sizes: list[int], bpp: int) -> bool:\n    return (\n        all(o % bpp == 0 for o in offsets)\n        and offsets == sorted(offsets)\n        and all(s > bpp for s in sizes)\n    )\n\nassert valid_batch(offsets, sizes, client.bytes_per_page)\nclient.batch_read(offsets, sizes)","typeGuard":"def is_page_aligned_batch(offsets, sizes, bytes_per_page):\n    return isinstance(offsets, list) and isinstance(sizes, list) and valid_batch(offsets, sizes, bytes_per_page)","tryCatchPattern":"try:\n    client.batch_read(offsets, sizes)\nexcept ValueError as e:\n    if 'Hf3fsClient.check' in str(e):\n        client = recreate_client()  # check() closed it\n        offsets, sizes = realign_to_pages(offsets, sizes, client.bytes_per_page)\n        client.batch_read(offsets, sizes)\n    else:\n        raise","preventionTips":["Always compute offsets as slot * bytes_per_page; never pass raw slot indices","Remember check() closes the client on failure — recreate rather than reuse"],"tags":["hf3fs","validation","alignment","batch-io"],"backgroundTag":"unaligned-io-request","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}