nautechsystems/nautilus_trader · error
`batch_size` must be greater than zero
Error message
`batch_size` must be greater than zero
What it means
read_bulk_batched fetches Redis keys in batches of batch_size using MGET-style reads. A batch size of zero would loop forever or produce empty batches, so the function validates the argument up front and bails. This is a defensive parameter check on a public API.
Source
Thrown at crates/infrastructure/src/redis/queries.rs:210
Ok(bytes_results)
}
/// Bulk reads multiple keys from Redis using MGET, batched into chunks.
///
/// Keys are batched into chunks of `batch_size` to avoid exceeding Redis
/// request size limits on some providers.
///
/// # Errors
///
/// Returns an error if `batch_size` is zero or if the underlying Redis MGET operation fails.
pub async fn read_bulk_batched(
con: &ConnectionManager,
keys: &[String],
batch_size: usize,
) -> anyhow::Result<Vec<Option<Bytes>>> {
if batch_size == 0 {
anyhow::bail!("`batch_size` must be greater than zero");
}
if keys.is_empty() {
return Ok(vec![]);
}
let mut all_results: Vec<Option<Bytes>> = Vec::with_capacity(keys.len());
for chunk in keys.chunks(batch_size) {
let mut con = con.clone();
let results: Vec<Option<Vec<u8>>> =
redis::cmd("MGET").arg(chunk).query_async(&mut con).await?;
all_results.extend(results.into_iter().map(|opt| opt.map(Bytes::from)));
}
Ok(all_results)View on GitHub (pinned to 18893faf8b)
Solutions
- Pass a batch_size >= 1, e.g. saturate at the call site with batch_size.max(1).
- Validate/normalize the batch-size config value at startup before calling this function.
- Guard derived values: if batch size is computed, clamp it to a sensible minimum (e.g. 100).
- Note the empty-keys early return already returns Ok(vec![]) — only pass keys when non-empty and pair with a positive batch size.
Example fix
// before let values = read_bulk_batched(&con, &keys, config.batch_size).await?; // after let batch = config.batch_size.max(1); let values = read_bulk_batched(&con, &keys, batch).await?;
Defensive patterns
Strategy: validation
Validate before calling
// Rust: clamp batch size before calling let batch_size = config.batch_size.unwrap_or(256).max(1); assert!(batch_size > 0, "batch_size must be positive");
Type guard
fn positive_batch_size(n: usize) -> Option<usize> {
if n == 0 { None } else { Some(n) }
} Try / catch
match read_bulk_batched(&con, &keys, batch_size).await {
Ok(values) => { /* use values */ }
Err(e) if e.to_string().contains("batch_size") => {
// retry once with a safe default
read_bulk_batched(&con, &keys, 256).await
}
Err(e) => return Err(e),
} Prevention
- Never allow batch-size config to default to 0; enforce a positive minimum at parse time.
- Clamp computed batch sizes (e.g. .max(1)) before calling batched APIs.
- Rely on the empty-keys early return instead of special-casing empty inputs yourself.
- Unit-test batched readers with batch_size edge values (0 and 1).
When it happens
Trigger: Calling read_bulk_batched with batch_size == 0 — e.g. a computed batch size from an empty/default config value, or a caller deriving batch size from a slice length that happens to be zero.
Common situations: Configuration where a batch-size setting defaults to 0 or is parsed from an empty string; math like keys.len() / divisor yielding 0; passing through a user-supplied value without validation.
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
- Invalid hash index payload for '{index_key}': expected field
- heartbeat_interval_secs must be greater than 0
- Invalid topic format: {stream_msg:?}
- Invalid type format: {stream_msg:?}
- Invalid payload kind format: {stream_msg:?}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e0a80d48d0f2c04f.
Report an issue: GitHub.