sgl-project/sglang · error · ValueError
group_concurrent_contiguous requires equal-length src/dst in
Error message
group_concurrent_contiguous requires equal-length src/dst index arrays, got {src_indices.size} and {dst_indices.size} What it means
group_concurrent_contiguous groups src/dst page indices into concurrent contiguous runs for batched KV transfer. It requires src_indices.size == dst_indices.size (both non-empty; empty inputs short-circuit earlier). A length mismatch means the prefill-side page list and decode-side allocation list do not correspond 1:1, which would corrupt the transfer.
Source
Thrown at python/sglang/srt/disaggregation/common/utils.py:123
dst_addr = dst_aux_ptr + item_len * aux_index
buffer = (ctypes.c_byte * len(data)).from_address(dst_addr)
buffer[:] = data
return
def group_concurrent_contiguous(
src_indices: npt.NDArray[np.int32], dst_indices: npt.NDArray[np.int32]
) -> Tuple[List[npt.NDArray[np.int32]], List[npt.NDArray[np.int32]]]:
"""Vectorised NumPy implementation."""
# src/dst indices are transferred pairwise, so an empty side means there is
# nothing to transfer. Guarding both sides (not just src) avoids a cryptic
# NumPy broadcast error from np.diff() below when only one side is empty, e.g.
# a non-empty prefill DSA/SWA state list paired with an empty decode registration.
if src_indices.size == 0 or dst_indices.size == 0:
return [], []
if src_indices.size != dst_indices.size:
raise ValueError(
"group_concurrent_contiguous requires equal-length src/dst index arrays, "
f"got {src_indices.size} and {dst_indices.size}"
)
brk = np.where((np.diff(src_indices) != 1) | (np.diff(dst_indices) != 1))[0] + 1
src_groups = np.split(src_indices, brk)
dst_groups = np.split(dst_indices, brk)
src_groups = [g.tolist() for g in src_groups]
dst_groups = [g.tolist() for g in dst_groups]
return src_groups, dst_groups
@dataclasses.dataclass(frozen=True)
class DCPTokenTransferPlan:
src_token_indices: npt.NDArray[np.int64]
dst_token_indices: npt.NDArray[np.int64]View on GitHub (pinned to 0132848349)
Solutions
- Log both arrays' lengths and content at the call site and reconcile which side is wrong (usually the decode allocation count vs prefill page count)
- Ensure prefix/padding math produces identical token->page counts on both servers (same page_size, same padding)
- If developing against the helper, pass arrays already validated as equal length
Example fix
# before group_concurrent_contiguous(src_pages, dst_pages) # len mismatch -> ValueError # after assert src_pages.size == dst_pages.size, (src_pages.size, dst_pages.size) group_concurrent_contiguous(src_pages, dst_pages)
Defensive patterns
Strategy: validation
Validate before calling
assert src_indices.size == dst_indices.size, (src_indices.size, dst_indices.size)
Type guard
def _valid_index_pair(src: np.ndarray, dst: np.ndarray) -> bool:
return src.size == dst.size and src.size > 0 Prevention
- Assert equal page counts before every send_kvcache call
- Keep page_size identical on both servers so token->page mapping matches
When it happens
Trigger: Calling send_kvcache / _send_kvcache_generic / send_kvcache_dcp / _send_swa_dsa_state with page-index arrays of different lengths, e.g. prefill computed N pages but decode registration/allocations returned M != N indices.
Common situations: Prefill and decode disagree on prefix length or page count (e.g. chunked prefill boundary off-by-page); decode allocator returned fewer pages for a request; races where one side was updated for an aborted request. Also exercised directly in unit tests of the grouping helper.
Related errors
- num_kv_tokens must fit in the provided source pages, got tok
- KVTransferError(self.bootstrap_room, failure_reason)
- NIXL KVSender Exception
- v_cache must be provided
- q can only be None when only_qv=True
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/a0f87763ee7f0455.
Report an issue: GitHub.