One untagged tuple is one namespace, not two
In multi-tenant serving, the prefix cache is a shared database and the block hash is its only access control. vLLM v0.31.0 fixed a key collision that proves the point.
The bug, from the merged PR: block hashes mixed LoRA adapter names, cache_salt values, multimodal ids and prompt-embeds digests into a single untagged tuple. A LoRA request for adapter foo and a base-model request with cache_salt "foo" produced the same first-block hash for the same prompt tokens. Either request could be served KV computed with the other's weights. A caller could pick a salt that landed inside an adapter's namespace on purpose.
The fix is the textbook one: tag every key by its source, ("lora", name) versus ("cache_salt", salt), so equal values from different fields cannot hash the same. A follow-up PR adds the adapter path to the key, because re-pointing a name at a different adapter kept serving the old KV until eviction.
Upgrade cost: one cold-cache cycle, every block with LoRA or salt keys misses once. KV events keep their old shapes, so external KV-aware routers keep decoding. An in-place adapter reload from the same path is still undetected, you get a warning, publish under a new path instead.
The trap: when two request fields can write the same bytes into one untagged key, you built one namespace, not two. cache_salt read like a tenancy boundary while it was spoofable.
The issue sat four months with one comment; read the Security section of your engine's release notes before the Highlights.
- Tagged extra keys: LoRA name vs cache_salt collision fix — vLLM PR #51899 Sep 30, 2026
- LoRA path added to block hash (re-pointed adapter names) — vLLM PR #59335 Oct 01, 2026
- v0.31.0 release notes, Security section Oct 05, 2026
- Original report — vLLM issue #44701 Jun 06, 2026