From 8ba790e8ad1af86d89711cd4d2280eedb32c7394 Mon Sep 17 00:00:00 2001 From: Joel Farthing Date: Sat, 1 Aug 2026 01:17:04 -0500 Subject: [PATCH] state: fix V cache compatibility check for models with no V cache (#2212) read_kv_cache_data gated the restore on kv_self.v_trans != (v_state == 1). v_state == 2 records that the writer had no V cache, while v_trans tracks flash attention rather than V allocation, so with -fa 0 on a K-only or MLA cache the two disagree and the restore is refused. Compare V cache presence in both directions, and transposition only when a V cache exists on both sides. The write path and serialized layout are unchanged. Co-authored-by: Joel Farthing <262452229+joelfarthing@users.noreply.github.com> --- src/llama.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/llama.cpp b/src/llama.cpp index be9214b8..79e66adf 100644 --- a/src/llama.cpp +++ b/src/llama.cpp @@ -9907,9 +9907,14 @@ struct llama_data_read { return false; } - // Currently the only way there is no V cache (and thus v_state is 2) requires flash_attn, and flash_attn sets kv_self.v_trans to false - if (kv_self.v_trans != (v_state == 1)) { - LLAMA_LOG_ERROR("%s: incompatible V transposition\n", __func__); + // v_state == 2 means the writer had no V cache at all. Transposition is meaningless in that + // case, and kv_self.v_trans is independent of whether v_l was ever allocated, so it says + // nothing about compatibility here. V cache presence has to match in both directions; + // transposition only has to match when there actually is a V cache on both sides. + if (((v_state == 2) != kv_self.v_l.empty()) || + (v_state != 2 && kv_self.v_trans != (v_state == 1))) { + LLAMA_LOG_ERROR("%s: incompatible V cache state (v_state = %u, v_l %s, v_trans = %d)\n", + __func__, v_state, kv_self.v_l.empty() ? "empty" : "present", (int) kv_self.v_trans); return false; }