Skip to content

Fix merge and search with an empty multivector placeholder - #10870

Merged
xzfc merged 5 commits into
qdrant:devfrom
drakeo338:claude/10857-fix
Oct 1, 2026
Merged

xzfc merged 5 commits into
qdrant:devfrom
drakeo338:claude/10857-fix

Conversation

@drakeo338

@drakeo338 drakeo338 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #10857.

adding a multivector to an indexed collection broke merges and search because of the empty placeholder, this makes merge and search accept it, tests for f32/u8/f16

Both commits are AI-made (Claude Code). Initial prompt: "Fix #10857: adding a multivector named vector to an indexed collection breaks the optimizer merge and queries; add regression tests."

  • [AI] Support empty multivector placeholder in merge and search
  • [AI] Cover uint8 and float16 placeholders in merge, tidy multivector view

All Submissions:

  • My PR targets the dev branch (not master) and my branch was created from dev.
  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same update/change?

New Feature Submissions:

  1. Does your submission pass tests?
  2. Have you formatted your code locally using cargo +nightly fmt --all command prior to submission?
  3. Have you checked your code using cargo clippy --workspace --all-features command?

Changes to Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully ran tests with your changes locally?

A named multivector added to an existing segment is backed by an
EmptyDense placeholder that carries a multivector config. Merging it
into a multi-dense target failed with "source is not a f32 multi-dense
storage", and a multivector query against it failed with a multi/regular
conversion error.

Read it as one zero inner vector per deleted slot when merging, and
score multivector queries through a multi-dense view of the placeholder.

Fixes qdrant#10857
Read an EmptyDense placeholder as zeros in the dense uint8/float16 and
multi uint8/float16 merge readers too, not only float32. Turbo readers
are left out: their record size comes from the target's quantizer.

Make the multivector view expect a multivector config instead of
inventing MaxSim, score the placeholder in the raw scorer test, and
move test imports to module level.
@qdrant-cloud-bot qdrant-cloud-bot added the area/segment lib/segment — storage, vector & payload index internals label Sep 30, 2026
@qdrant qdrant deleted a comment from coderabbitai Bot Oct 1, 2026
@IvanPleshkov
IvanPleshkov self-requested a review October 1, 2026 10:33
timvisee and others added 3 commits October 1, 2026 13:57
A named Turbo4 vector added to an existing segment is backed by an
EmptyDense placeholder. Merging it into a turbo target failed with
"source is not a turbo storage" (or "multi turbo storage"), turning the
collection red.

Read it as one zero record per deleted slot, the same bytes turbo
storages write for their own deleted slots. The record size depends
only on dim and distance, so compute it without building a quantizer.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Cover the single-file, appendable and multivector turbo targets, and
pin the record size helper to the quantizer it mirrors.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Replace the per-storage merge tests with one parametrized test that
opens each target through open_vector_storage, as the segment builder
does: every datatype, dense and multivector, single-file and appendable.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@qdrant qdrant deleted a comment from coderabbitai Bot Oct 1, 2026
@timvisee
timvisee self-requested a review October 1, 2026 14:28
@qdrant qdrant deleted a comment from coderabbitai Bot Oct 1, 2026

@timvisee timvisee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking this up!

I've added some changes to apply the same treatment elsewhere.

@timvisee
timvisee requested a review from xzfc October 1, 2026 15:13
@xzfc
xzfc merged commit 9ae05ef into qdrant:dev Oct 1, 2026
18 checks passed
timvisee added a commit that referenced this pull request Oct 5, 2026
* Support empty multivector placeholder in merge and search

A named multivector added to an existing segment is backed by an
EmptyDense placeholder that carries a multivector config. Merging it
into a multi-dense target failed with "source is not a f32 multi-dense
storage", and a multivector query against it failed with a multi/regular
conversion error.

Read it as one zero inner vector per deleted slot when merging, and
score multivector queries through a multi-dense view of the placeholder.

Fixes #10857

* Cover uint8 and float16 placeholders in merge, tidy multivector view

Read an EmptyDense placeholder as zeros in the dense uint8/float16 and
multi uint8/float16 merge readers too, not only float32. Turbo readers
are left out: their record size comes from the target's quantizer.

Make the multivector view expect a multivector config instead of
inventing MaxSim, score the placeholder in the raw scorer test, and
move test imports to module level.

* Support empty Turbo4 placeholder in merge

A named Turbo4 vector added to an existing segment is backed by an
EmptyDense placeholder. Merging it into a turbo target failed with
"source is not a turbo storage" (or "multi turbo storage"), turning the
collection red.

Read it as one zero record per deleted slot, the same bytes turbo
storages write for their own deleted slots. The record size depends
only on dim and distance, so compute it without building a quantizer.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* Test merging empty Turbo4 placeholders

Cover the single-file, appendable and multivector turbo targets, and
pin the record size helper to the quantizer it mirrors.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* Consolidate empty placeholder merge tests

Replace the per-storage merge tests with one parametrized test that
opens each target through open_vector_storage, as the segment builder
does: every datatype, dense and multivector, single-file and appendable.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

---------

Co-authored-by: timvisee <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
@timvisee timvisee mentioned this pull request Oct 5, 2026
@timvisee

timvisee commented Oct 7, 2026

Copy link
Copy Markdown
Member

This is included in Qdrant 1.19.2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/segment lib/segment — storage, vector & payload index internals

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants