sgl-project/sglang · error · ValueError
`g_cache` must have shape [slots, HV, L, K].
Error message
`g_cache` must have shape [slots, HV, L, K].
What it means
The ReplaySSM gate cache g_cache must be [slots, HV, L, K]: grouped by value heads (num_v_heads), length matching d_cache, and last dim equal to key_dim (the gate shares the key dimension even though it lives on the HV head group). The wrapper validates g_cache.shape[1:] against (num_v_heads, cache_length, key_dim) before kernel selection. A mismatch usually means the gate cache was sized with value_dim or the wrong head count.
Source
Thrown at python/sglang/kernels/ops/attention/helion/kda_replayssm.py:742
raise ValueError("`write_pos` must be a 1D int32 tensor.")
if write_pos.shape != (batch,):
raise ValueError(f"`write_pos` must have shape {(batch,)}.")
if force_flush is not None and (
force_flush.ndim != 1
or force_flush.dtype is not torch.int32
or force_flush.shape != (batch,)
):
raise ValueError("`force_flush` must be a length-B int32 tensor or None.")
cache_length = d_cache.size(2)
if cache_length < 1:
raise ValueError("ReplaySSM cache length must be at least 1.")
if d_cache.shape[1:] != (num_v_heads, cache_length, value_dim):
raise ValueError("`d_cache` must have shape [slots, HV, L, V].")
if k_cache.shape[1:] != (num_q_heads, cache_length, key_dim):
raise ValueError("`k_cache` must have shape [slots, H, L, K].")
if g_cache.shape[1:] != (num_v_heads, cache_length, key_dim):
raise ValueError("`g_cache` must have shape [slots, HV, L, K].")
if g_cache.dtype is not torch.float32:
raise ValueError("`g_cache` must have dtype torch.float32.")
device = mixed_qkv.device
if any(
tensor.device != device for tensor in (d_cache, k_cache, g_cache, write_pos)
):
raise ValueError("ReplaySSM inputs must be on the same device.")
if force_flush is not None and force_flush.device != device:
raise ValueError("`force_flush` must be on the same device as the inputs.")
cache_block = helion.next_power_of_2(max(16, cache_length))
use_lower_bound = lower_bound is not None
kernel = _select_replayssm_decode_kernel(
is_bf16_state=initial_state.dtype is torch.bfloat16,
num_v_heads=num_v_heads,
)
result = kernel(View on GitHub (pinned to 0132848349)
Solutions
- Allocate g_cache as [slots, num_v_heads, cache_length, key_dim] with the same cache_length as d_cache
- Double-check the last dim is key_dim (not value_dim) — the gate is per-key-channel decay
- Ensure all three caches share the same slots and L; add an assert in your allocation helper
Example fix
# before g_cache = torch.empty(slots, num_v_heads, cache_len, value_dim, dtype=torch.float32, device='cuda') # after g_cache = torch.empty(slots, num_v_heads, cache_len, key_dim, dtype=torch.float32, device='cuda')
Defensive patterns
Strategy: validation
Validate before calling
assert g_cache.shape[1:] == (num_v_heads, d_cache.size(2), key_dim), g_cache.shape
Type guard
def valid_g_cache(t: torch.Tensor, hv: int, k: int, l: int) -> bool:
return t.ndim == 4 and t.shape[1:] == (hv, l, k) Prevention
- g_cache last dim is key_dim, not value_dim
- Write one shape-check helper for d/k/g caches and call it right before the kernel
When it happens
Trigger: Calling helion_fused_recurrent_kda_replayssm_decode with g_cache whose shape[1:] != (num_v_heads, d_cache.size(2), key_dim) — e.g. allocated with value_dim as the last dim, or grouped by num_q_heads, or a different cache length than d_cache.
Common situations: Copy-paste allocation of d/k/g caches where g_cache accidentally uses d_cache's dims; hybrid-model state pools whose shape tuple was updated for d but not g; tests exercising the per-row flush contract with hand-built caches.
Related errors
- `d_cache` must have shape [slots, HV, L, V].
- `k_cache` must have shape [slots, H, L, K].
- `g_cache` must have dtype torch.float32.
- `mixed_qkv` must be a 2D tensor (got ndim={mixed_qkv.ndim}).
- `a` and `b` must be 2D tensors (got a.ndim={a.ndim}, b.ndim=
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/5205c8331ae7704a.
Report an issue: GitHub.