sgl-project/sglang · error · NotImplementedError

walk_radix_cache_for_canary does not support {type(radix_cac

Error message

walk_radix_cache_for_canary does not support {type(radix_cache).__name__}

What it means

The internal lock-state helper _node_is_unlocked_for_canary reads node.lock_ref for RadixCache and node.full_lock_ref for SWARadixCache; any other exact cache type is unsupported and raises NotImplementedError. This guards the canary sweep from selecting locked (in-use) nodes.

Source

Thrown at python/sglang/srt/kv_canary/radix_cache_walker.py:139

def _node_slots_for_canary(*, node: TreeNode) -> list[int]:
    value: Any = node.value
    if isinstance(value, torch.Tensor):
        return [int(s) for s in value.tolist()]
    return []


def _node_is_unlocked_for_canary(
    *,
    node: TreeNode,
    radix_cache: BasePrefixCache,
) -> bool:
    if type(radix_cache) is RadixCache:
        return node.lock_ref == 0

    if type(radix_cache) is SWARadixCache:
        return node.full_lock_ref == 0

    raise NotImplementedError(
        f"walk_radix_cache_for_canary does not support {type(radix_cache).__name__}"
    )


def _node_is_swa_resident_for_canary(
    *,
    node: TreeNode,
    radix_cache: BasePrefixCache,
) -> bool:
    if type(radix_cache) is SWARadixCache:
        return not node.swa_tombstone

    return True

View on GitHub (pinned to 0132848349)

Solutions

  1. Use one of the supported concrete cache types when running canary sweeps
  2. For a new cache type, add a branch to _node_is_unlocked_for_canary defining its unlocked predicate
  3. Audit callers of walk_radix_cache_for_canary (e.g. build_verify_plan_radix_sweep) to confirm they pass a supported cache

Example fix

// before
unlocked = _node_is_unlocked_for_canary(radix_cache=my_subclass, node=n)
# after
unlocked = (n.lock_ref == 0) if isinstance_cache_supported else extend_walker_for(my_subclass)
Defensive patterns

Strategy: type-guard

Validate before calling

from sglang.srt.mem_cache.radix_cache import RadixCache, SWARadixCache
if type(radix_cache) not in (RadixCache, SWARadixCache):
    raise TypeError('unsupported cache for canary lock check')

Type guard

def unlocked(cache, node) -> bool:
    if type(cache) is RadixCache:
        return node.lock_ref == 0
    if type(cache) is SWARadixCache:
        return node.full_lock_ref == 0
    raise NotImplementedError(type(cache).__name__)

Prevention

When it happens

Trigger: A radix cache whose exact type is neither RadixCache nor SWARadixCache reaching _walk_radix_subtree, typically because the public walker's dispatch (line 38) allowed a subclass or the walker was called directly in tests with a custom cache.

Common situations: Subclassing RadixCache with a different lock accounting field; mocked cache objects; new cache variants where the canary lock predicate is undefined.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/07c099ab776de8ed. Report an issue: GitHub.