From e3b78655557b77f8cea62b05f541d3b5f16a38d4 Mon Sep 17 00:00:00 2001 From: Basem Barakat Date: Wed, 14 Oct 2026 19:53:00 -0500 Subject: [PATCH] [Core][Bugfix] Drop bounded_replay when promoting SlidingWindowMLASpec With the hybrid KV cache manager disabled, _promote_local_kv_cache_specs rebuilds each SlidingWindowMLASpec as an MLAAttentionSpec via replace_as, which forwards every field of the source spec. bounded_replay (added in #56227) exists only on SlidingWindowMLASpec, so the rebuild raises TypeError: MLAAttentionSpec.__init__() got an unexpected keyword argument 'bounded_replay' and any sliding-window MLA model (DeepSeek-V4) fails at KV cache planning under --disable-hybrid-kv-cache-manager. A promoted spec keeps every block, so the window-bounded replay is moot, as extra_retained_tokens already is. Signed-off-by: Basem Barakat Co-authored-by: Cursor --- tests/v1/core/test_kv_cache_planning.py | 10 ++++++++++ vllm/v1/core/kv_cache_planning.py | 5 +++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/v1/core/test_kv_cache_planning.py b/tests/v1/core/test_kv_cache_planning.py index d60a18878086..0a55a5ed0ae4 100644 --- a/tests/v1/core/test_kv_cache_planning.py +++ b/tests/v1/core/test_kv_cache_planning.py @@ -1783,6 +1783,16 @@ def test_unify_hybrid_kv_cache_specs(): kv_cache_planning.unify_hybrid_kv_cache_specs(kv_cache_spec) +def test_unify_hybrid_kv_cache_specs_swa_mla(): + swa = replace(new_swa_mla_spec(), bounded_replay=True) + kv_cache_spec = {"full": new_mla_spec(), "swa": swa} + kv_cache_planning.unify_hybrid_kv_cache_specs(kv_cache_spec) + promoted = kv_cache_spec["swa"] + assert type(promoted) is MLAAttentionSpec + assert promoted.sliding_window == swa.sliding_window + assert promoted.page_size_bytes == swa.page_size_bytes + + def test_unify_kv_cache_spec_page_size_mamba(): """Regression test for https://github.com/vllm-project/vllm/issues/43626. diff --git a/vllm/v1/core/kv_cache_planning.py b/vllm/v1/core/kv_cache_planning.py index 4d73f4303e2f..2b98d2e9ad75 100644 --- a/vllm/v1/core/kv_cache_planning.py +++ b/vllm/v1/core/kv_cache_planning.py @@ -801,8 +801,9 @@ def promoted_page_size_padded(spec: AttentionSpec, block_size: int) -> int | Non spec, target_cls, # Promoted specs allocate blocks for all tokens and never free - # below the window, so the trailing-edge extension is moot. - drop=("extra_retained_tokens",), + # below the window, so the trailing-edge extension and the + # window-bounded prefix replay are both moot. + drop=("extra_retained_tokens", "bounded_replay"), block_size=block_size, page_size_padded=promoted_page_size_padded(spec, block_size), )