risingwavelabs/risingwave · error · ValueEncodingError

Invalid struct encoding: {0}

Error message

Invalid struct encoding: {0}

What it means

ValueEncodingError::InvalidStructEncoding wraps a crate::array::ArrayError and is raised when deserializing a struct datum fails. deserialize_struct (src/common/src/util/value_encoding/mod.rs:398-405) decodes each field via inner_deserialize_datum; if any nested field's array/datum decoding errors, it is surfaced as this variant via the wrapped ArrayError source. The inner ArrayError tells you which nested element actually failed.

Source

Thrown at src/common/src/util/value_encoding/error.rs:35

#[derive(Error, Debug)]
pub enum ValueEncodingError {
    #[error("Invalid bool value encoding: {0}")]
    InvalidBoolEncoding(u8),
    #[error("Invalid UTF8 value encoding: {0}")]
    InvalidUtf8(#[from] std::string::FromUtf8Error),
    #[error("Invalid Date value encoding: days: {0}")]
    InvalidDateEncoding(i32),
    #[error("invalid Timestamp value encoding: secs: {0} nsecs: {1}")]
    InvalidTimestampEncoding(i64, u32),
    #[error("invalid Time value encoding: secs: {0} nano: {1}")]
    InvalidTimeEncoding(u32, u32),
    #[error("Invalid null tag value encoding: {0}")]
    InvalidTagEncoding(u8),
    #[error("Invalid jsonb encoding")]
    InvalidJsonbEncoding,
    #[error("Invalid variant encoding")]
    InvalidVariantEncoding,
    #[error("Invalid struct encoding: {0}")]
    InvalidStructEncoding(
        #[source]
        #[backtrace]
        crate::array::ArrayError,
    ),
    #[error("Invalid list encoding: {0}")]
    InvalidListEncoding(
        #[source]
        #[backtrace]
        crate::array::ArrayError,
    ),
    #[error("Invalid flag: {0:b}")]
    InvalidFlag(u8),
    #[error("Invalid vector item: {0} {1}")]
    InvalidVectorItem(f32, String),
}

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect the wrapped ArrayError source to find the failing nested field
  2. Ensure the reader's StructType matches the schema used when the row was written
  3. Handle schema evolution via column-id based (column-aware) encoding instead of positional struct decoding
  4. Re-materialize affected rows after fixing the schema mismatch

Example fix

// before: positional struct decode with mismatched schema
let v = deserialize_struct(&new_schema, data)?; // InvalidStructEncoding
// after: decode with the schema recorded for those bytes
let stored = StructType::from_stored_field_ids(data)?;
let v = deserialize_struct(&stored, data)?;
Defensive patterns

Strategy: try-catch

Validate before calling

fn struct_type_matches(stored: &StructType, expected: &StructType) -> bool {
    stored.types().eq(expected.types())
}

Type guard

fn is_compatible_struct(def: &StructType, row_bytes_len: usize, fields: usize) -> bool {
    def.len() == fields && row_bytes_len >= fields // cheap pre-check before full decode
}

Try / catch

match deserialize_datum(&DataType::Struct(def), data) {
    Ok(v) => { /* use value */ }
    Err(ValueEncodingError::InvalidStructEncoding(src)) => {
        tracing::error!("struct field decode failed: {src}"); // inspect ArrayError source
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Decoding a DataType::Struct row whose nested field bytes are truncated or of the wrong type; struct written with a different number/order of fields than the reader's StructType.

Common situations: Schema evolution on a struct column (field added/removed/reordered) while old rows are still on disk; version skew between writer and reader; corrupted state-store bytes; NULL/default handling differences across versions.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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