diff --git a/python/sglang/srt/disaggregation/prefill.py b/python/sglang/srt/disaggregation/prefill.py index 3d541d522..4de1bfdb7 100644 --- a/python/sglang/srt/disaggregation/prefill.py +++ b/python/sglang/srt/disaggregation/prefill.py @@ -666,10 +666,12 @@ class SchedulerDisaggregationPrefillMixin: continue if getattr(req, "is_chunked", 0) != 0 or getattr(req, "start_send_idx", 0) != 0: continue # chunked / partially-sent: this forward isn't the full range - prefix = getattr(req, "prefix_indices", None) - # NB: prefix_indices is a tensor — never use `or`/truthiness on it. - if prefix is not None and len(prefix) != 0: - continue # cached prefix is HiCache-loaded, not forward-written -> lever B + # Cover the FULL sequence (cached prefix + new tokens). The per-layer + # backup hook fires after each layer's full processing, by which point + # layer L's HiCache-loaded prefix KV and forward-written new KV are both + # final — so transferring all of layer L's pages then is correct, and it + # overlaps the (dominant, at high cache-hit) prefix transfer with the + # forward. Verified by output-equality. end_idx = min(len(req.fill_ids), len(req.origin_input_ids)) page_indices = _kv_locs_to_page_indices_cpu( self.req_to_token_pool.req_to_token[req.req_pool_idx, 0:end_idx],