risingwavelabs/risingwave · error · ValueEncodingError

Invalid flag: {0:b}

Error message

Invalid flag: {0:b}

What it means

ValueEncodingError::InvalidFlag(u8) is raised when the header byte of a column-aware encoded row (src/common/src/util/value_encoding/column_aware_row_encoding.rs:477-481) does not carry the expected magic bit pattern. EncodedBytes::new parses the first byte with Header::from_bits and rejects it if header.magic() is false, formatting the raw byte in binary ({0:b}). It means the bytes being decoded are not a valid column-aware value row at all.

Source

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

    #[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. Confirm the bytes come from the column-aware serializer (first byte's magic bit set) before decoding
  2. Use the correct deserializer variant matching the storage format/version for those rows
  3. Check for version skew and migrate/rewrite rows stored in the legacy format
  4. If corruption is suspected, restore from replica or re-materialize the affected data

Example fix

// before: assuming format
let row = ColumnAwareDeserializer::deserialize(bytes)?; // InvalidFlag
// after: check format first
fn is_column_aware(bytes: &[u8]) -> bool {
    Header::from_bits(*bytes.first().unwrap_or(&0)).magic()
}
let row = if is_column_aware(bytes) {
    ColumnAwareDeserializer::deserialize(bytes)?
} else {
    LegacyValueRowDeserializer::deserialize(bytes)?
};
Defensive patterns

Strategy: validation

Validate before calling

fn has_column_aware_magic(bytes: &[u8]) -> bool {
    bytes.len() >= 5 && Header::from_bits(bytes[0]).magic()
}

Type guard

fn is_column_aware_row(bytes: &[u8]) -> bool {
    bytes.first().map_or(false, |b| Header::from_bits(*b).magic())
}

Try / catch

match EncodedBytes::new(bytes) {
    Ok(encoded) => { /* iterate columns */ }
    Err(ValueEncodingError::InvalidFlag(header)) => {
        tracing::error!("bad row header {header:#010b}; wrong format or corrupt data");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling the column-aware deserializer on bytes that are empty, truncated (fewer than 5 header bytes), or produced by the legacy/other row encoding (e.g. plain ValueRowSerializer or serialize_datum output).

Common situations: Version skew where old rows were stored in a previous row format before the column-aware format with magic header existed; pointing a decoder at the wrong key/sst region; data corruption; mixing serializer outputs in tests or manual replay tools.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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