databendlabs/databend · error
sample size must be greater than zero
Error message
sample size must be greater than zero
What it means
FixedSizeSampler::new builds a reservoir sampler with capacity k, and internally represents k as a NonZeroUsize. This panic fires when a caller constructs a FixedSizeSampler with k == 0, which is meaningless for reservoir sampling (the sampler would never retain rows). The library treats a zero sample size as a programming error rather than a runtime condition.
Solutions
- Ensure the sample size passed to FixedSizeSampler::new is at least 1 before constructing the sampler.
- Validate the user-facing setting (e.g. sample size option) and return a proper error like ErrorCode::IllegalScalar for 0 instead of reaching the sampler.
- If 0 is legitimate, skip sampling entirely and use an empty result rather than constructing a sampler.
Example fix
// before let sampler = FixedSizeSampler::new(sample_size, rng); // after assert!(sample_size > 0, "sample_size setting must be positive"); let sampler = FixedSizeSampler::new(sample_size.max(1), rng);
Defensive patterns
Strategy: validation
Validate before calling
if sample_size == 0 {
return Err(ErrorCode::IllegalScalar("sample size must be greater than zero"));
}
let sampler = FixedSizeSampler::new(sample_size, rng); Type guard
fn valid_sample_size(k: usize) -> bool { k > 0 } Prevention
- Validate sampling-related settings at query compile time, not inside the sampler.
- Treat 0 as 'no sampling needed' and short-circuit before constructing a sampler.
When it happens
Trigger: Calling FixedSizeSampler::new(0, rng), or passing a k value computed from configuration/other code that evaluates to 0 (e.g. an unset or empty sampling setting).
Common situations: A sampling size config option left at 0 or defaulted incorrectly; a query setting like SAMPLE_SIZE=0; an off-by-one computation of the requested sample size before constructing the sampler.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/f1ab44731de2d5f5.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/expression/src/sampler/fixed_size_sampler.rs:37
/// A fixed-capacity owning reservoir sampler using Vitter's Algorithm L.
///
/// Like Spark's `reservoirSampleAndCount`, the reservoir owns at most `k` values and also tracks
/// the input cardinality. Algorithm L replaces Spark's per-row Algorithm R decision with an exact
/// skip calculation, avoiding work for rows that cannot enter the reservoir. Input block boundaries
/// do not affect the resulting sample.
pub struct FixedSizeSampler<T, R: Rng> {
samples: Vec<T>,
k: usize,
rows_seen: usize,
// Zero-based global stream index selected next by Algorithm L.
next_sample: Option<usize>,
core: AlgoL<R>,
}
impl<T, R: Rng> FixedSizeSampler<T, R> {
pub fn new(k: usize, rng: R) -> Self {
let k = NonZeroUsize::new(k).expect("sample size must be greater than zero");
Self {
samples: Vec::with_capacity(k.get()),
k: k.get(),
rows_seen: 0,
next_sample: None,
core: AlgoL::new(k, rng),
}
}
/// Consider one logical block while preserving the same result as one continuous row stream.
///
/// `value_at` is evaluated only for rows entering the reservoir: every row during the initial
/// fill, then only the rows selected by Algorithm L.
pub fn add_block<F>(&mut self, rows: usize, mut value_at: F)
where F: FnMut(usize) -> T {
let start = self.rows_seen;
let end = start.checked_add(rows).expect("sample row count overflow");
let mut row = 0;View on GitHub (pinned to 288d84d76e)