{"record":{"id":"d041f811511a0057","repo":"sgl-project/sglang","slug":"protected-size-is-not-implemented-use-full-prot","errorCode":null,"errorMessage":"protected_size() is not implemented; use full_protected_size() and swa_protected_size() instead","messagePattern":"protected_size\\(\\) is not implemented; use full_protected_size\\(\\) and swa_protected_size\\(\\) instead","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/mem_cache/swa_radix_cache.py","lineNumber":865,"sourceCode":"            node = node.parent\n\n    def sanity_check(self):\n        self.full_lru_list.sanity_check(self)\n        self.swa_lru_list.sanity_check(self)\n\n    def evictable_size(self) -> Tuple[int, int]:\n        # Note: use full_evictable_size() and swa_evictable_size() instead.\n        raise NotImplementedError\n\n    def full_evictable_size(self) -> int:\n        return self.full_evictable_size_\n\n    def swa_evictable_size(self) -> int:\n        return self.swa_evictable_size_\n\n    def protected_size(self) -> Tuple[int, int]:\n        # Note: use full_protected_size() and swa_protected_size() instead.\n        raise NotImplementedError\n\n    def full_protected_size(self) -> int:\n        # protected size refers to the size of the full cache that is locked\n        return self.full_protected_size_\n\n    def swa_protected_size(self) -> int:\n        # protected size refers to the size of the swa cache that is locked\n        return self.swa_protected_size_\n\n    def all_values_flatten(self) -> torch.Tensor:\n        values = []\n\n        def _dfs_helper(node: TreeNode):\n            for _, child in node.children.items():\n                values.append(child.value)\n                _dfs_helper(child)\n\n        _dfs_helper(self.root_node)","sourceCodeStart":847,"sourceCodeEnd":883,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/mem_cache/swa_radix_cache.py#L847-L883","documentation":"Symmetric to evictable_size: SWARadixCache splits protected sizes into full and SWA domains, so protected_size() raises NotImplementedError by design. Use full_protected_size() and swa_protected_size().","triggerScenarios":"Calling protected_size() on SWARadixCache from generic cache accounting code.","commonSituations":"Scheduler/metrics code ported from the non-SWA RadixCache path that queries protected_size.","solutions":["Use full_protected_size() and swa_protected_size()","Guard with hasattr/try when supporting both SWA and non-SWA caches"],"exampleFix":"# before\nprot = tree.protected_size()\n# after\nprot_full = tree.full_protected_size()\nprot_swa = tree.swa_protected_size()","handlingStrategy":"validation","validationCode":"if hasattr(tree, 'swa_protected_size'):\n    prot = (tree.full_protected_size(), tree.swa_protected_size())","typeGuard":"def has_split_protected_sizes(tree) -> bool:\n    return hasattr(tree, 'full_protected_size') and hasattr(tree, 'swa_protected_size')","tryCatchPattern":null,"preventionTips":["Never call protected_size() unconditionally; feature-detect split accessors","Write shared helpers returning (full, swa) tuples for SWA-aware caches"],"tags":["swa","radix-cache","not-implemented","api-misuse"],"backgroundTag":"method-not-implemented","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}