risingwavelabs/risingwave · error · ArrayError

Must have at least one element in offsets

Error message

Must have at least one element in offsets

What it means

During `ListArray::from_protobuf`, the flattened length is derived from the last element of `array_data.offsets`. If `offsets` is empty there is no way to compute the cardinality of the nested value array, so decoding is rejected.

Source

Thrown at src/common/src/array/list_array.rs:264

        &self.value
    }

    pub fn from_protobuf(array: &PbArray) -> ArrayResult<ArrayImpl> {
        ensure!(
            array.values.is_empty(),
            "Must have no buffer in a list array"
        );
        debug_assert!(
            (array.array_type == PbArrayType::List as i32)
                || (array.array_type == PbArrayType::Map as i32),
            "invalid array type for list: {}",
            array.array_type
        );
        let bitmap: Bitmap = array.get_null_bitmap()?.into();
        let array_data = array.get_list_array_data()?.to_owned();
        let flatten_len = match array_data.offsets.last() {
            Some(&n) => n as usize,
            None => bail!("Must have at least one element in offsets"),
        };
        let value = ArrayImpl::from_protobuf(array_data.value.as_ref().unwrap(), flatten_len)?;
        let arr = ListArray {
            bitmap,
            offsets: array_data.offsets.into(),
            value: Box::new(value),
        };
        Ok(arr.into())
    }

    /// Apply the function on the underlying elements.
    /// e.g. `map_inner([[1,2,3],NULL,[4,5]], DOUBLE) = [[2,4,6],NULL,[8,10]]`
    pub fn map_inner_sync<E, F>(self, f: F) -> std::result::Result<ListArray, E>
    where
        F: FnOnce(ArrayImpl) -> std::result::Result<ArrayImpl, E>,
    {
        let new_value = (f)(*self.value)?;

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Ensure `ListArray::to_protobuf` (or equivalent) always writes at least one offsets entry (starting at 0).
  2. Check that the source chunk is not truncated and `list_array_data` is fully populated.
  3. Validate `array_data.offsets` is non-empty upstream and produce a clearer error.
  4. Look for recent changes to list-array serialization that may have omitted offsets.

Example fix

// before
let flatten_len = match array_data.offsets.last() {
    Some(&n) => n as usize,
    None => bail!("Must have at least one element in offsets"),
};
// after (caller-side guard)
ensure!(!pb_array.get_list_array_data()?.offsets.is_empty(), "list array payload missing offsets");
let arr = ListArray::from_protobuf(&pb_array)?;
Defensive patterns

Strategy: validation

Validate before calling

let data = pb_array.get_list_array_data()?;
if data.offsets.is_empty() { return Err("list array offsets empty".into()); }

Type guard

fn has_offsets(a: &PbArray) -> bool {
    a.get_list_array_data().map(|d| !d.offsets.is_empty()).unwrap_or(false)
}

Prevention

When it happens

Trigger: Calling `ListArray::from_protobuf` on a PbArray whose `list_array_data.offsets` vector is empty — e.g. the serializer failed to write offsets or the payload was truncated/hand-built without them.

Common situations: Manually constructed protobuf in tests missing offsets; data corruption in transit/storage; a serializer bug after schema evolution that drops the offsets field.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/bb5b6eeb3831f911. Report an issue: GitHub.