risingwavelabs/risingwave · error · HummockError

Decode error

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.

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.

Appendix: 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)