Files
qdrant/lib/api
Marcelo Machuca 4d00a5e628 fix(api): reject empty multi-vector in flattened vectors_count path (#9308)
`validate_multi_vector_len(N, &[])` with N > 0 previously returned Ok:
it passes the `vectors_count != 0` check, an empty `flatten_dense_vector`
clears the size check, and `0.is_multiple_of(N)` is true, so it falls into
the Ok branch. The unvalidated value then reaches
`convert_to_plain_multi_vector`, where `dim = data.len() / vectors_count = 0`,
the divisibility check `dim * vectors_count != data.len()` (0 == 0) passes,
and `data.into_iter().chunks(0)` panics (itertools asserts the chunk size is
non-zero). This is reachable from a single malformed gRPC Upsert via the
deprecated `vectors_count` field.

Add an `is_empty()` guard to `validate_multi_vector_len`, mirroring the
sibling `validate_multi_vector_by_length`, so empty flattened data is
rejected with a clear validation error before any conversion. Also add a
defensive `vectors_count == 0 || data.is_empty()` guard at the top of
`convert_to_plain_multi_vector`, which aligns it with the already-guarded
`MultiDenseVectorInternal::try_from_flatten` and closes the same panic on the
internal node-to-node `sync` path (where validation is log-only and
`SyncPoints.points` is not validated).

This completes the empty-vector hardening started in #9070, which covered the
REST side only and did not touch the gRPC flattened `vectors_count` form.

Includes a regression test covering both the rejected (empty) and accepted
(consistent multivector) cases.
2026-06-04 10:28:18 +02:00
..