diff --git a/python/sglang/srt/mem_cache/hi_mamba_radix_cache.py b/python/sglang/srt/mem_cache/hi_mamba_radix_cache.py index a08b2a33c..2157bcc55 100644 --- a/python/sglang/srt/mem_cache/hi_mamba_radix_cache.py +++ b/python/sglang/srt/mem_cache/hi_mamba_radix_cache.py @@ -277,6 +277,10 @@ class HiMambaRadixCache(MambaRadixCache): super().reset() def write_backup(self, node: TreeNode, write_back=False): + # Backup invariant: parent must be backed up before child. + if node.parent != self.root_node and not node.parent.backuped: + return + # If mamba host slot already exists, refresh its LRU position. if node.mamba_value is not None and node.mamba_host_value is not None: if self.mamba_host_lru_list.in_list(node): diff --git a/python/sglang/srt/mem_cache/hiradix_cache.py b/python/sglang/srt/mem_cache/hiradix_cache.py index 3c1e97daa..fd75f859d 100644 --- a/python/sglang/srt/mem_cache/hiradix_cache.py +++ b/python/sglang/srt/mem_cache/hiradix_cache.py @@ -608,6 +608,10 @@ class HiRadixCache(RadixCache): return False def write_backup(self, node: TreeNode, write_back=False): + # Backup invariant: parent must be backed up before child. + if node.parent != self.root_node and not node.parent.backuped: + return + host_indices = self.cache_controller.write( device_indices=node.value, node_id=node.id, @@ -836,6 +840,8 @@ class HiRadixCache(RadixCache): def _evict_regular(self, node: TreeNode): # evict a node not initiated write to host -- emit BlockRemoved + assert len(node.children) == 0, f"non-leaf, {node.id=}" + self._record_remove_event(node) self.cache_controller.mem_pool_device_allocator.free(node.value) num_evicted = len(node.value)