Skip to content

fix(index): return error instead of panicking when hierarchical k-means can't reach target_k#7869

Merged
wjones127 merged 1 commit into
lance-format:mainfrom
wjones127:fix/ivf-kmeans-partition-error
Jul 21, 2026
Merged

fix(index): return error instead of panicking when hierarchical k-means can't reach target_k#7869
wjones127 merged 1 commit into
lance-format:mainfrom
wjones127:fix/ivf-kmeans-partition-error

Conversation

@wjones127

Copy link
Copy Markdown
Contributor

Summary

Creating an IVF index with num_partitions large enough to trigger hierarchical k-means (> 256) could fail badly when the training data can't be split into that many non-empty clusters (small dataset and/or many near-duplicate vectors):

  • Debug builds: hard panic at debug_assert_eq!(heap.len(), target_k) in train_hierarchical_kmeans.
  • Release builds: the assert compiles out, silently producing far fewer than num_partitions non-empty partitions, degrading recall with no error.

This replaces the debug_assert_eq! with a returned ArrowError::InvalidArgumentError describing how many clusters could actually be formed, so both build types fail cleanly instead of panicking or silently degrading. The error propagates through train_kmeansdo_train_ivf_model as a normal Result.

Test plan

  • Added test_hierarchical_kmeans_too_few_distinct_vectors_errors, which builds a heavily near-duplicated dataset with num_partitions (300) far exceeding the number of distinct vectors, and asserts a descriptive error is returned instead of a panic.
  • Verified this test panics against the old debug_assert_eq! code (reproducing the reported issue) and passes with the fix.
  • cargo test -p lance-index --lib vector:: (318 tests) passes.
  • cargo fmt --all -- --check and cargo clippy -p lance-index --tests --benches -- -D warnings pass.

Fixes #7867

…ns can't reach target_k

num_partitions large enough to trigger hierarchical k-means (>256) could
panic on debug_assert_eq!(heap.len(), target_k) in debug builds, or
silently build a half-empty centroid set in release builds, when the
training data can't be split into that many non-empty clusters (small
dataset and/or many near-duplicate vectors).

Return a descriptive InvalidArgumentError instead, which propagates
through train_kmeans and do_train_ivf_model as a normal Result.

Fixes lance-format#7867
@github-actions github-actions Bot added the A-index Vector index, linalg, tokenizer label Jul 20, 2026
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The fix addresses #7867 by returning an InvalidArgumentError when hierarchical k-means can't form enough clusters.
Out of Scope Changes check ✅ Passed The changes appear scoped to the reported hierarchical k-means failure and the new regression test.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title clearly matches the main change: returning an error when hierarchical k-means cannot reach target_k.
Description check ✅ Passed The description accurately summarizes the bug, fix, and test coverage for hierarchical k-means training.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the bug Something isn't working label Jul 20, 2026
@wjones127

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@wjones127
wjones127 marked this pull request as ready for review July 20, 2026 18:49
@wjones127
wjones127 requested a review from BubbleCal July 20, 2026 18:49
@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@wjones127
wjones127 merged commit a3c6fce into lance-format:main Jul 21, 2026
33 checks passed
wjones127 added a commit that referenced this pull request Jul 21, 2026
…ns can't reach target_k (#7869)

## Summary

Creating an IVF index with `num_partitions` large enough to trigger
hierarchical k-means (> 256) could fail badly when the training data
can't be split into that many non-empty clusters (small dataset and/or
many near-duplicate vectors):

- Debug builds: hard panic at `debug_assert_eq!(heap.len(), target_k)`
in `train_hierarchical_kmeans`.
- Release builds: the assert compiles out, silently producing far fewer
than `num_partitions` non-empty partitions, degrading recall with no
error.

This replaces the `debug_assert_eq!` with a returned
`ArrowError::InvalidArgumentError` describing how many clusters could
actually be formed, so both build types fail cleanly instead of
panicking or silently degrading. The error propagates through
`train_kmeans` → `do_train_ivf_model` as a normal `Result`.

## Test plan

- Added `test_hierarchical_kmeans_too_few_distinct_vectors_errors`,
which builds a heavily near-duplicated dataset with `num_partitions`
(300) far exceeding the number of distinct vectors, and asserts a
descriptive error is returned instead of a panic.
- Verified this test panics against the old `debug_assert_eq!` code
(reproducing the reported issue) and passes with the fix.
- `cargo test -p lance-index --lib vector::` (318 tests) passes.
- `cargo fmt --all -- --check` and `cargo clippy -p lance-index --tests
--benches -- -D warnings` pass.

Fixes #7867

(cherry picked from commit a3c6fce)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-index Vector index, linalg, tokenizer bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IVF index build panics (debug) / silently builds half-empty index (release) when hierarchical k-means can't reach num_partitions

2 participants