[Rust] IndexParams/SearchParams setters silently accept invalid values — add validated builder
Nobody has claimed this yet.
- Dominant language
- Cuda
- Stars
- 854
- Forks
- 236
- Avg merge
- 3d 3h
- Merged PRs (30d)
- 62
Description
Environment
- cuVS: 26.2 (crates.io)
- CUDA: 12.4
- GPU: T4 (sm_75)
- Rust: 1.82 (MSRV)
Problem
IndexParams setter methods return Self unconditionally. Invalid parameter
values are accepted at configuration time and only surface as an opaque CUDA
assertion inside Index::build() — after GPU memory has already been allocated
and graph construction has started.
// This compiles. It runs. It says nothing.
// ~1.8 seconds later, during Index::build():
let params = IndexParams::new()?
.set_graph_degree(0) // graph_degree=0 is invalid for CAGRA
.set_intermediate_graph_degree(0) // must be >= graph_degree
.set_nn_descent_niter(0); // must be > 0 for convergence
// Error surfaces here:
// cuvsError { code: CUVS_ERROR, text: "raft::exception: assertion failed" }
// No field name. No valid range. No hint.
let _index = Index::build(&res, ¶ms, &dataset)?;
The same problem affects SearchParams (set_hashmap_max_fill_rate(1.5),
set_team_size(7)) and IndexParams for ivf_pq, ivf_flat, and vamana.
When CAGRA parameters are loaded from a config file at runtime, a
misconfiguration blocks the GPU thread for the full build duration before
producing an error that names neither the offending field nor its valid range.
Root Cause
The C API (cuvsCagraBuild) validates parameters on entry and returns
CUVS_ERROR on failure. The Rust bindings expose setters that write directly
to the FFI struct without pre-validation, so constraints documented in the C
header are invisible to callers until Index::build() fires.
Proposed Fix
Add IndexParams::builder() — a parallel, additive entry point that validates
all parameters in a single build() -> Result<IndexParams> call before any
FFI allocation occurs. Existing IndexParams::new()?.set_graph_degree(...) is
unchanged.
pub struct IndexParamsBuilder { /* private */ }
impl IndexParamsBuilder {
pub fn graph_degree(mut self, v: usize) -> Self;
pub fn intermediate_graph_degree(mut self, v: usize) -> Self;
pub fn nn_descent_niter(mut self, v: usize) -> Self;
// ... remaining fields
/// Validate parameters in pure Rust (no GPU needed).
pub fn validate(&self) -> Result<()>;
/// Validate all parameters and allocate the FFI struct.
///
/// Returns `Err` with a message naming the offending field and its valid
/// range before any GPU work begins.
pub fn build(self) -> Result<IndexParams>;
}
impl IndexParams {
pub fn builder() -> IndexParamsBuilder;
}
Usage:
let params = IndexParams::builder()
.graph_degree(32)
.intermediate_graph_degree(64)
.nn_descent_niter(20)
.build()?;
// Err("graph_degree must be > 0; got 0") fires immediately,
// not 1.8s later inside Index::build()
Validation rules (derived from C header constraints):
graph_degree > 0; multiple of 32 preferred for warp alignmentintermediate_graph_degree >= graph_degreenn_descent_niter > 0itopk_sizemust be a power of 2hashmap_max_fill_rate∈ (0.1, 0.9)team_size∈ {0, 4, 8, 16, 32}
Backward Compatibility
The existing IndexParams::new() API and all setter methods are unchanged.
The builder is purely additive. No call sites break.
Scope
Rust bindings only. No C API changes required. The validation logic duplicates
constraints already enforced by the C layer — we are surfacing them earlier,
before the FFI call, with useful error messages.
A proof-of-concept implementation is available at:
https://github.com/zbennett10/cuvs/tree/feat/rust-validated-index-params-builder
Files
rust/cuvs/src/error.rs— addimpl From<String> for Errorrust/cuvs/src/cagra/index_params.rs—IndexParamsBuilderrust/cuvs/src/cagra/search_params.rs—SearchParamsBuilderrust/cuvs/src/cagra/mod.rs— re-export builder types- Apply same pattern to
ivf_pq,ivf_flat,vamanafor consistency
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with rust/cuvs/src/cagra/index_params.rs, rust/cuvs/src/cagra/search_params.rs, rust/cuvs/src/cagra/mod.rs, and rust/cuvs/src/error.rs to understand the existing setters, error type, and exports. Compare the C-header constraints listed in the issue with the CAGRA, IVF-PQ, IVF-flat, and Vamana parameter APIs. Done means additive builders validate before FFI allocation, return field-specific errors, and preserve the existing setter API.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100