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
- Ensure the payload was serialized with VariantVal::value_serialize from a matching RisingWave version
- Align reader/writer versions to eliminate format skew
- Rewrite the affected rows (re-ingest or refresh the materialization)
- 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
- Use VariantVal::value_serialize exclusively for persisting variants
- Verify length prefix matches payload length before decoding
- Add encode/decode round-trip tests for variant columns
- Align RisingWave versions across writer and reader nodes
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
- Invalid jsonb encoding
- Invalid bool value encoding: {0}
- Invalid Date value encoding: days: {0}
- invalid Timestamp value encoding: secs: {0} nsecs: {1}
- invalid Time value encoding: secs: {0} nano: {1}
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/869a3da3868fd27b.
Report an issue: GitHub.