risingwavelabs/risingwave · error · ValueEncodingError

Invalid variant encoding

Error message

Invalid variant encoding

What it means

ValueEncodingError::InvalidVariantEncoding is thrown when a Variant column's stored bytes cannot be deserialized into a VariantVal. In deserialize_value for DataType::Variant (src/common/src/util/value_encoding/mod.rs:386-389), VariantVal::value_deserialize returns None for malformed payloads and the code raises this error. It signals that the persisted variant bytes are corrupt or written in an incompatible format.

Source

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

use thiserror::Error;

#[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. Ensure the payload was serialized with VariantVal::value_serialize from a matching RisingWave version
  2. Align reader/writer versions to eliminate format skew
  3. Rewrite the affected rows (re-ingest or refresh the materialization)
  4. Validate variant payloads before persistence

Example fix

// before
let val = VariantVal::value_deserialize(bytes).ok_or(ValueEncodingError::InvalidVariantEncoding)?;
// after: check length prefix against actual slice length first
let (len, rest) = (u32::from_le_bytes(bytes[..4].try_into().unwrap()) as usize, &bytes[4..]);
assert_eq!(len, rest.len(), "truncated variant payload");
let val = VariantVal::value_deserialize(rest).ok_or(ValueEncodingError::InvalidVariantEncoding)?;
Defensive patterns

Strategy: try-catch

Validate before calling

fn valid_variant_payload(bytes: &[u8]) -> bool {
    !bytes.is_empty() && VariantVal::value_deserialize(bytes).is_some()
}

Type guard

fn is_decodable_variant(bytes: &[u8]) -> Option<VariantVal> {
    VariantVal::value_deserialize(bytes)
}

Try / catch

match deserialize_datum(&DataType::Variant, data) {
    Ok(Some(datum)) => { /* use datum */ }
    Ok(None) => { /* NULL datum */ }
    Err(ValueEncodingError::InvalidVariantEncoding) => {
        tracing::error!("corrupt variant bytes; skip or rewrite row");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling deserialize_value/deserialize_datum on DataType::Variant where the length-prefixed bytea payload is not valid variant binary encoding (truncation, foreign writer, format-version mismatch).

Common situations: Reading rows written by a cluster version with a different variant layout; data ingested/persisted by an external tool; corrupted storage bytes; hand-crafted bytes passed to the deserializer in tests.

Related errors


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