sgl-project/sglang · error · ValueError
num_kv_tokens must fit in the provided source pages, got tok
Error message
num_kv_tokens must fit in the provided source pages, got tokens={num_kv_tokens}, capacity={source_capacity} What it means
build_dcp_token_transfer_plan computes source_capacity = len(src_pages) * physical_page_size and validates 0 <= num_kv_tokens <= source_capacity (num_kv_tokens defaults to full capacity when None). A token count exceeding the source pages means the plan would read past the allocated prefill KV pages.
Source
Thrown at python/sglang/srt/disaggregation/common/utils.py:168
dcp_rank: int,
src_page_offset: int = 0,
decode_prefix_len: int = 0,
num_kv_tokens: Optional[int] = None,
) -> DCPTokenTransferPlan:
virtual_page_size = physical_page_size * dcp_size
if decode_prefix_len % virtual_page_size != 0:
raise ValueError(
"PD DCP transfer requires decode_prefix_len to align to the virtual "
f"DCP page size ({virtual_page_size}), got {decode_prefix_len}"
)
src_pages = np.asarray(src_page_indices, dtype=np.int64)
dst_pages = np.asarray(dst_page_indices, dtype=np.int64)
source_capacity = src_pages.size * physical_page_size
if num_kv_tokens is None:
num_kv_tokens = source_capacity
if not 0 <= num_kv_tokens <= source_capacity:
raise ValueError(
"num_kv_tokens must fit in the provided source pages, "
f"got tokens={num_kv_tokens}, capacity={source_capacity}"
)
if src_pages.size == 0:
empty = np.empty((0,), dtype=np.int64)
return DCPTokenTransferPlan(empty, empty.copy())
chunk_start = decode_prefix_len + src_page_offset * physical_page_size
first_owned_offset = (dcp_rank - chunk_start) % dcp_size
owned_offsets = np.arange(
first_owned_offset, num_kv_tokens, dcp_size, dtype=np.int64
)
src_token_indices = (
src_pages[owned_offsets // physical_page_size] * physical_page_size
+ owned_offsets % physical_page_size
)
relative_positions = src_page_offset * physical_page_size + owned_offsetsView on GitHub (pinned to 0132848349)
Solutions
- Recompute num_kv_tokens from the actual src page list: num_kv_tokens = min(desired, len(src_pages) * physical_page_size)
- Check that src_page_indices covers the full range you intend to transfer (include pages from all prefill chunks)
- If you want 'everything', pass num_kv_tokens=None to use full capacity
Example fix
# before
plan = build_dcp_token_transfer_plan(..., src_page_indices=pages,
num_kv_tokens=total_seq_len) # pages only cover a chunk
# after
plan = build_dcp_token_transfer_plan(..., src_page_indices=all_pages,
num_kv_tokens=min(total_seq_len, all_pages.size * page_size)) Defensive patterns
Strategy: validation
Validate before calling
capacity = src_page_indices.size * physical_page_size
if num_kv_tokens is not None:
assert 0 <= num_kv_tokens <= capacity, (num_kv_tokens, capacity) Prevention
- Derive num_kv_tokens from the actual page list, or pass None for full capacity
- Unit-test chunked-prefill boundary arithmetic
When it happens
Trigger: Calling send_kvcache_dcp with num_kv_tokens larger than the provided src_page_indices can hold — e.g. passing the full sequence length while src pages cover only the chunked-prefill portion, or negative token counts.
Common situations: Chunked prefill where num_kv_tokens was computed as total input length but src pages only cover the current chunk; off-by-one in prefix/seq_len arithmetic; passing per-page count instead of token count.
Related errors
- PD peers must connect matching DCP ranks, got prefill={self.
- Unsupported PD DCP topology: {self.dcp_size} -> {dst_dcp_siz
- PD DCP source/destination KV geometry differs: src={src_toke
- PD decode DCP requires an MLA or hybrid-MLA KV pool.
- PD decode DCP currently requires prefill attention CP=1, got
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/f901ef75e037ae8c.
Report an issue: GitHub.