Skip to content

RotatingKVCache.to_quantized() raises NotImplementedError — blocks --kv-bits on Gemma 4's sliding-window attention layers #1573

Description

@chrislyons

Symptom

mlx_lm/models/cache.py:552 (confirmed on current main, and on the 0.31.3 release):

def to_quantized(self, group_size: int = 64, bits: int = 4) -> QuantizedKVCache:
    raise NotImplementedError("RotatingKVCache Quantization NYI")

mlx_lm.server --kv-bits N crashes on the first inference request with this NotImplementedError, even though the server itself starts cleanly and reports healthy. The crash only surfaces once a request actually needs to quantize a rotating-window cache slot.

Affected models

Gemma 4 (both E4B and the 26B-A4B MoE variant) use sliding-window attention on the majority of transformer layers — 35 of 42 layers in the 26B-A4B configuration. Sliding-window layers are backed by RotatingKVCache, which has no quantized implementation. Full-attention layers use the (already-quantizable) standard KVCache, so the crash is specific to models with a mixed/hybrid attention schedule like Gemma 4, not to dense-attention models.

Repro

mlx_lm.server --model <gemma-4-26b-a4b-path> --kv-bits 8 --port 41966
# server starts, /health returns 200
# first /v1/chat/completions request → NotImplementedError: RotatingKVCache Quantization NYI

Current workaround (in production use since ~FCT093)

We monkeypatch mlx_lm.models.cache.make_prompt_cache (and mlx_lm.server.make_prompt_cache) before the server starts, forcing every cache slot — rotating or not — into an 8-bit QuantizedKVCache directly, bypassing the broken RotatingKVCache.to_quantized() path entirely:

from mlx_lm.models.cache import QuantizedKVCache, RotatingKVCache

def make_prompt_cache_quantized(model, max_kv_size=None, group_size=64, bits=8):
    return [QuantizedKVCache(group_size=group_size, bits=bits) for _ in model.layers]

import mlx_lm.models.cache
mlx_lm.models.cache.make_prompt_cache = make_prompt_cache_quantized
import mlx_lm.server
mlx_lm.server.make_prompt_cache = make_prompt_cache_quantized

This works but means --kv-bits on the CLI is silently ignored for these models — anyone hitting this for the first time gets a runtime crash instead of a clear "unsupported for this cache type" error at startup.

Ask

Either implement RotatingKVCache.to_quantized() (mirroring how QuantizedKVCache already handles the non-rotating case), or fail fast at server startup with a clear error when --kv-bits is combined with a model whose cache config includes any RotatingKVCache layers, instead of a first-request NotImplementedError.

Related

Companion MoE-specific issue on the mlx-vlm side: Blaizzy/mlx-vlm#904 (TurboQuant KV quantization crash on Gemma-4-E4B) — same underlying use case (quantized KV cache on Gemma 4), different repo/entry point.

Version: mlx-lm 0.31.3 (production), reproduced on current main (mlx_lm/models/cache.py:552, unchanged since at least 2026-04-21).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions