quickwit-oss/quickwit · error

storekey encode ordinal

Error message

storekey encode ordinal: {}

What it means

append_prefix_col_to_key serializes a row-key entry as (ordinal, value) into a byte buffer using the storekey crate. This error is returned when storekey fails to encode the ordinal portion (the u64 row ordinal) before the value bytes are appended. It wraps the underlying storekey::encode error message.

Solutions

  1. Read the inner storekey error in the message to identify which Encode impl failed
  2. Ensure the buffer passed in is a valid, writable Vec<u8> (caller passes &mut *buf)
  3. Verify the ordinal type used matches the expected fixed-width integer supported by storekey
  4. Check storekey version compatibility between writer and reader code paths

Example fix

// before: opaque wrap
storekey::encode(&mut *buf, &ordinal).map_err(|e| anyhow!("storekey encode ordinal: {}", e))?;
// after: add context about buffer state
storekey::encode(&mut *buf, &ordinal).map_err(|e| anyhow!("storekey encode ordinal (buf_len={}): {}", buf.len(), e))?;
Defensive patterns

Strategy: try-catch

Validate before calling

assert!(buf.capacity() >= buf.len() + size_of::<u64>() + value.len());

Try / catch

match encode_row_key(&mut buf, ordinal, value, descending) {
    Err(e) if e.to_string().contains("storekey encode ordinal") => { /* log + inspect buffer/type */ }
    Err(e) => return Err(e),
    Ok(()) => {},
}

Prevention

When it happens

Trigger: Calling encode_row_key/encode_byte_array_value/encode_prefix_col_value when the underlying storekey encoder rejects the ordinal type — e.g. buffer write failures or an unsized/mis-typed T violates the storekey::Encode bound at runtime.

Common situations: Building row keys for sorted series during parquet-engine index writes; a corrupted or oversized output buffer, or a storekey codec version mismatch between encoder and reader.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/4406588168ed0504. Report an issue: GitHub.

Appendix: source

Thrown at quickwit/quickwit-parquet-engine/src/sorted_series/mod.rs:292

///
/// Layout: `storekey(ordinal: u8) || storekey(value)`. For descending
/// columns the *value* bytes are inverted in place (NOT the ordinal
/// byte) so memcmp on the composite reverses the value's lex order
/// while ordinals stay in declared order. Caller skips this function
/// entirely for null columns — the next column's higher ordinal byte
/// then appears in this column's place, which gives nulls-last
/// ordering without a sentinel marker (matches the writer's
/// `nulls_first=false` convention).
pub(crate) fn append_prefix_col_to_key<T>(
    buf: &mut Vec<u8>,
    ordinal: u8,
    value: &T,
    descending: bool,
) -> Result<()>
where
    T: ?Sized + storekey::Encode,
{
    storekey::encode(&mut *buf, &ordinal).map_err(|e| anyhow!("storekey encode ordinal: {}", e))?;
    let value_start = buf.len();
    storekey::encode(&mut *buf, value).map_err(|e| anyhow!("storekey encode value: {}", e))?;
    if descending {
        invert_bytes(&mut buf[value_start..]);
    }
    Ok(())
}

/// Bitwise-NOT a byte slice in place, inverting the sort order for
/// descending columns in the composite key. This is the standard
/// ordered-code technique: if ascending bytes A < B, then !A > !B,
/// so memcmp on the inverted bytes gives descending order.
fn invert_bytes(bytes: &mut [u8]) {
    for byte in bytes.iter_mut() {
        *byte = !*byte;
    }
}

View on GitHub (pinned to a39730c5cd)