risingwavelabs/risingwave · error · HummockError
invalid iter key range
Error message
invalid iter key range: {table_id} {left:?} {right:?} What it means
Hummock iterator was given a key range whose left bound is greater than its right bound, which is invalid for a forward iterator. In debug builds this panics; in release builds it returns HummockError::other with this message.
Solutions
- Check the code that builds the iterator range to ensure left <= right
- Validate user-supplied scan bounds (start/end keys) before passing them to Hummock iterators
- Reproduce in a debug build to get a panic with a stack trace pinpointing the caller
- Inspect how the table's key range was derived (e.g. from SST metadata) for corruption
Example fix
// before let iter = store.iter(table_id, end_key, start_key).await?; // after assert!(start_key <= end_key, "reversed range"); let iter = store.iter(table_id, start_key, end_key).await?;
Defensive patterns
Strategy: validation
Validate before calling
fn validate_range(left: &[u8], right: &[u8]) -> Result<(), String> {
if left > right { Err(format!("invalid range: {:?} > {:?}", left, right)) } else { Ok(()) }
} Try / catch
let (left, right) = if start_key <= end_key {
(start_key, end_key)
} else {
(end_key, start_key) // or reject
}; Prevention
- Always normalize scan ranges so start <= end before iterating
- Test range construction with reversed/empty user bounds
- Assert bound ordering in debug builds around iterator creation
When it happens
Trigger: Calling iter_with_memtable or rev_iter-derived iter_inner on a HummockVersion/table where bound_inner(left) > bound_inner(right), i.e. start key exceeds end key.
Common situations: Bugs in code constructing scan ranges (e.g. reversed user range scans, wrong bound ordering after prefix/limit handling), or corrupted range metadata for a table_id.
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
- Barrier read is unavailable for now. Likely the cluster is…
- Change log retention miss: table
- Checksum mismatch: expected
- Committed epoch mismatch: table
- CompactionExecutor error
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/c0980ea87ca17a99.
Report an issue: GitHub.
Appendix: source
Thrown at src/storage/src/hummock/store/version.rs:1017
committed: &CommittedVersion,
local_stats: &mut StoreLocalStatistic,
factory: &mut F,
) -> StorageResult<()> {
{
fn bound_inner<T>(bound: &Bound<T>) -> Option<&T> {
match bound {
Bound::Included(bound) | Bound::Excluded(bound) => Some(bound),
Bound::Unbounded => None,
}
}
let (left, right) = &table_key_range;
if let (Some(left), Some(right)) = (bound_inner(left), bound_inner(right))
&& right < left
{
if cfg!(debug_assertions) {
panic!("invalid iter key range: {table_id} {left:?} {right:?}")
} else {
return Err(HummockError::other(format!(
"invalid iter key range: {table_id} {left:?} {right:?}"
))
.into());
}
}
}
local_stats.staging_imm_iter_count = imms.len() as u64;
for imm in imms {
factory.add_batch_iter(imm);
}
// 2. build iterator from committed
// Because SST meta records encoded key range,
// the filter key range needs to be encoded as well.
let user_key_range = bound_table_key_range(table_id, &table_key_range);
let user_key_range_ref = (
user_key_range.0.as_ref().map(UserKey::as_ref),View on GitHub (pinned to 6469eb736d)