Skip to content

fix(index): check quantizer params before sampling training data - #9368

Open
LuciferYang wants to merge 5 commits into
lance-format:mainfrom
LuciferYang:fix/ivf-rq-quantizer-dead-code
Open

LuciferYang wants to merge 5 commits into
lance-format:mainfrom
LuciferYang:fix/ivf-rq-quantizer-dead-code

Conversation

@LuciferYang

Copy link
Copy Markdown
Contributor

Closes #9367

load_or_build_quantizer returns early when a quantizer is already set, so everything below that runs with self.quantizer == None. The tail match &self.quantizer could therefore only take its None arm, and that arm held the only check on quantizer_params — a builder given neither params nor a quantizer sampled the training data and computed residuals before failing. The params are now bound once at the top with let ... else, the tail collapses to the Q::build call, and sample_size_hint reads from that binding.

The None => 256 * 256 sample-size default went with it. Its comment says "here it must be retrain", but retrain arrives with quantizer: Some(..) and returns at the top, so that arm was unreachable; the case it was written for ended in the params error either way.

No behaviour changes for any reachable input. The params-missing path is only reachable by calling IvfIndexBuilder::new(.., None, ..) explicitly — the one constructor that leaves quantizer_params empty, new_incremental, sets quantizer at the same time — and that path produced the same error before, just later. So this is dead-code removal and a check moved earlier, not a fix for something a user can hit.

How was this patch tested?

No new test: there is no reachable input whose behaviour differs, so there is nothing new to pin. cargo test -p lance --lib index::vector covers the paths that do build a quantizer, including the incremental one that returns at the early exit.

load_or_build_quantizer sampled and residual-transformed the full
training dataset before checking whether quantizer build params were
set, wasting the entire pass when they were missing. The Some(q) match
arm after the early return was also dead code (the early return at the
top of the function already handles that case). Move the params check
before any IO and remove the dead arm.

Assisted-by: GLM-5.3
@github-actions github-actions Bot added the bug Something isn't working label Sep 18, 2026
lance-gatekeeper[bot]

This comment was marked as outdated.

@lance-gatekeeper lance-gatekeeper Bot added the K-changes Latest Gatekeeper recommendation requests changes. label Sep 18, 2026
@LuciferYang

Copy link
Copy Markdown
Contributor Author

Added test_load_or_build_quantizer_checks_params_before_sampling. The subtlety is that both orders end in the same error message, so the test points the builder at a column the dataset does not have: with the check first the call reports the missing params, with the check back below the sampling it reports column no_such_column does not exist in schema. I confirmed that by moving the guard back and watching the test fail with exactly that message.

@lance-gatekeeper lance-gatekeeper Bot removed the K-changes Latest Gatekeeper recommendation requests changes. label Sep 18, 2026

@lance-gatekeeper lance-gatekeeper Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Gate recommendation: approve.

The follow-up closes the earlier coverage gap: the new test distinguishes validation-before-sampling from the old order by making sampling fail on an invalid column. The upfront guard is a focused fix and preserves the preloaded-quantizer path.

@lance-gatekeeper lance-gatekeeper Bot added the K-approved Latest Gatekeeper recommendation permits acceptance. label Sep 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working K-approved Latest Gatekeeper recommendation permits acceptance.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: load_or_build_quantizer validates its params after sampling, and carries a dead match arm

1 participant