fix(cache): a hit that reconstructs to nothing must not be silent
Measured on Gemma-4-26B (mixed-SWA, allow-listed VL family), turn 3 of a media conversation: Paged cache hit for X: 42 blocks, checkpoint_tokens=2638 MLLM prefill cache-in for X: layer0=RotatingKVCache offset=0 cached_tokens=0 A 2,638-token hit was found, the rotating restore produced an EMPTY cache, and the turn re-prefilled in full -- with no log line anywhere saying so. From the outside that is indistinguishable from "the cache never had it", which is a large part of why the multimodal investigation took as long as it did: every silent restore failure reads as a cache miss. It now logs a WARNING naming the matched token count, the cache class, and the offset it came back at, and says explicitly that this is a restore failure rather than a miss. This does not yet FIX the Gemma restore itself. The mechanism is visible in the trace: turn 2 stores retained_tokens=2638 (42 blocks, terminal partial of 14), while the restore only accepts a rotating anchor whose logical offset equals block_table.num_tokens EXACTLY (prefix_cache.py, the rotating_kv arm of the block-restore). Turn 3 matches all 2,638 tokens, finds no anchor at 2,638, and silently yields nothing. That is the same class the fetch lanes already handle via _normalize_rotating_candidate -- a third site that did not get the walk-back.
J
Jinho Jang committed
8807f405e570cf35c11f1273b57c40837606d593
Parent: 3108a7d