risingwavelabs/risingwave · error · HummockError

Decode error: {0}

Error message

Decode error: {0}

What it means

A value read by Hummock failed to deserialize (decode) from its stored byte representation; the inner decoder's message is carried in the String payload. It is thrown when stored bytes cannot be converted back into the expected in-memory structure. This usually means the bytes on disk do not match what the current code expects.

Source

Thrown at src/storage/src/hummock/error.rs:35

use thiserror::Error;
use thiserror_ext::AsReport;
use tokio::sync::oneshot::error::RecvError;

// TODO(error-handling): should prefer use error types than strings.
#[derive(Error, thiserror_ext::ReportDebug, thiserror_ext::Arc)]
#[thiserror_ext(newtype(name = HummockError, backtrace))]
pub enum HummockErrorInner {
    #[error("Magic number mismatch: expected {expected}, found: {found}")]
    MagicMismatch { expected: u32, found: u32 },
    #[error("Invalid format version: {0}")]
    InvalidFormatVersion(u32),
    #[error("Checksum mismatch: expected {expected}, found: {found}")]
    ChecksumMismatch { expected: u64, found: u64 },
    #[error("Invalid block")]
    InvalidBlock,
    #[error("Encode error: {0}")]
    EncodeError(String),
    #[error("Decode error: {0}")]
    DecodeError(String),
    #[error("ObjectStore failed with IO error: {0}")]
    ObjectIoError(
        #[from]
        #[backtrace]
        ObjectError,
    ),
    #[error("Meta error: {0}")]
    MetaError(String),
    #[error("SharedBuffer error: {0}")]
    SharedBufferError(String),
    #[error("Wait epoch error: {0}")]
    WaitEpoch(String),
    #[error("Next epoch error: {0}")]
    NextEpoch(String),
    #[error("Change log retention miss: table {table_id}, epoch {epoch}")]
    ChangeLogRetentionMiss { table_id: TableId, epoch: u64 },
    #[error("Time-travel version expired: table {table_id}, epoch {epoch}")]

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Check whether the table schema or data types changed since the data was written; restore compatibility or rebuild the table.
  2. Pin all nodes to the same RisingWave version; avoid rolling upgrades across incompatible releases.
  3. If bytes are corrupt, delete the affected object and recover from replica/backup.
  4. Capture the wrapped decode message and report to maintainers if it reproduces on unchanged data.

Example fix

// before: altering column type then reading old data
ALTER TABLE t ALTER COLUMN c TYPE incompatible_new_type;
// after
CREATE TABLE t_new AS SELECT c::compatible_type AS c FROM t;  -- rebuild with migration
Defensive patterns

Strategy: try-catch

Try / catch

// Rust
match hummock_read(...) {
    Err(e) if e.to_string().starts_with("Decode error") => {
        // check schema drift; rebuild affected table, do not retry same data
    }
    r => r?,
}

Prevention

When it happens

Trigger: Reading/iterating SSTs or shared buffers where prost/row decoding of a value fails.

Common situations: Schema/type changes (ALTER TABLE, data type redefinition) after data was written; version upgrades changing wire format without migration; corrupted stored bytes.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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