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

  1. Check the code that builds the iterator range to ensure left <= right
  2. Validate user-supplied scan bounds (start/end keys) before passing them to Hummock iterators
  3. Reproduce in a debug build to get a panic with a stack trace pinpointing the caller
  4. 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

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


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)