{"record":{"id":"7e6cc869c6eee4f8","repo":"sgl-project/sglang","slug":"insufficient-destination-dcp-pages-required-requ","errorCode":null,"errorMessage":"Insufficient destination DCP pages: required={required_pages}, provided={dst_pages.size}, src_page_offset={src_page_offset}, dcp_rank={dcp_rank}","messagePattern":"Insufficient destination DCP pages: required=(.+?), provided=(.+?), src_page_offset=(.+?), dcp_rank=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/disaggregation/common/utils.py","lineNumber":193,"sourceCode":"\n    chunk_start = decode_prefix_len + src_page_offset * physical_page_size\n    first_owned_offset = (dcp_rank - chunk_start) % dcp_size\n    owned_offsets = np.arange(\n        first_owned_offset, num_kv_tokens, dcp_size, dtype=np.int64\n    )\n    src_token_indices = (\n        src_pages[owned_offsets // physical_page_size] * physical_page_size\n        + owned_offsets % physical_page_size\n    )\n\n    relative_positions = src_page_offset * physical_page_size + owned_offsets\n    dst_local_offsets = relative_positions // dcp_size\n    dst_page_ordinals = dst_local_offsets // physical_page_size\n    if dst_page_ordinals.size and (\n        dst_pages.size == 0 or int(dst_page_ordinals.max()) >= dst_pages.size\n    ):\n        required_pages = int(dst_page_ordinals.max()) + 1\n        raise ValueError(\n            \"Insufficient destination DCP pages: \"\n            f\"required={required_pages}, provided={dst_pages.size}, \"\n            f\"src_page_offset={src_page_offset}, dcp_rank={dcp_rank}\"\n        )\n\n    dst_token_indices = (\n        dst_pages[dst_page_ordinals] * physical_page_size\n        + dst_local_offsets % physical_page_size\n    )\n    return DCPTokenTransferPlan(src_token_indices, dst_token_indices)\n","sourceCodeStart":175,"sourceCodeEnd":204,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/disaggregation/common/utils.py#L175-L204","documentation":"After mapping destination token positions to page ordinals (dst_page_ordinals), the plan validates that the provided dst_pages list is long enough: the max ordinal must be < dst_pages.size. If not, it raises with required_pages and the dcp_rank/src_page_offset for debugging. This means the decode-side DCP allocation is too small for the tokens to be placed.","triggerScenarios":"send_kvcache_dcp where the destination page list for a DCP rank covers fewer pages than the transferred token span requires — e.g. decode allocated only part of the virtual-page span or a mis-set src_page_offset shifted positions.","commonSituations":"Decode allocator returning a short page run for the request; src_page_offset not accounting for prior DCP ranks' shares; prefix alignment issues inflating dst_local_offsets.","solutions":["Allocate more destination pages on decode for the request (check allocator accounting vs transfer span)","Verify src_page_offset matches which slice of the virtual pages this dcp_rank owns","Log dst_page_ordinals.max(), dst_pages.size and dcp_rank at the call site to see the shortfall"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"required = (dst_local_offsets.max() // physical_page_size) + 1 if dst_local_offsets.size else 0\nassert dst_pages.size >= required, (required, dst_pages.size)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify decode allocation spans the full virtual-page range before transfer","Cross-check src_page_offset against the dcp rank's slice"],"tags":["disaggregation","dcp","destination-pages","allocation"],"backgroundTag":"buffer-capacity-exceeded","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}