mirror of
https://github.com/qdrant/qdrant.git
synced 2026-08-04 09:01:00 -05:00
`EncodedVectorsTQ::layout()` declared `align_of::<f32>()`, but the size it reports is the packed dimensions plus a 4-byte-multiple extras trailer, which is not a multiple of 4 for three quarters of all dimensions (e.g. dim=756, Bits4: 378 + 4 = 382 bytes). The claim was never true — the encoded storage packs vectors at `id * quantized_vector_size` with no per-vector padding — and nothing relies on it: packed dimensions are read through unaligned SIMD loads (`loadu` / `vld1`) and the extras trailer through `f32::from_le_bytes` on a byte slice. It is also actively harmful. Inline HNSW storage packs link vectors back-to-back using this layout and rejects one whose size is not a multiple of its alignment, so building an index with `inline_storage` enabled fails for those dimensions — and retries forever as an optimization crashloop. Use `align_of::<u8>()`, matching scalar and product quantization. Old links files stay readable: both layouts are persisted in the file header and the reader takes size and alignment from there, never from the live quantizer. Add a test covering the `size % align == 0` invariant across awkward dimensions, bit widths, distances and modes — `layout()` had no coverage, which is why the mismatch went unnoticed on the multiple-of-32 dimensions everyone uses in practice. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>