risingwavelabs/risingwave · error · BackupError

unsupported metadata snapshot format version for hummock…

Error message

unsupported metadata snapshot format version for hummock sequence partial decoding: {}

What it means

decode_hummock_sequences_from_stream reads the snapshot header and requires format_version >= 2 to partially decode hummock sequences; older snapshots throw "unsupported metadata snapshot format version for hummock sequence partial decoding: {}". The partial (streaming) decoder only understands the V2 section layout.

Solutions

  1. Use MetaSnapshotV1 (full decode) for snapshots with format_version < 2 and read hummock sequences from the fully decoded model.
  2. Re-create the backup on a current RisingWave version so the snapshot is written in V2 format, then retry.
  3. Dispatch on the header format_version before choosing the decoder instead of assuming V2.
  4. If this hits during cluster upgrade, complete the meta store migration to V2 before taking new snapshots.

Example fix

// before: always partial V2 decode
let seqs = decode_hummock_sequences_from_stream(stream).await?;
// after: branch on version
let (version, _) = read_header(&stream).await?;
let seqs = if version >= 2 {
    decode_hummock_sequences_from_stream(stream).await?
} else {
    MetaSnapshotV1::decode(stream)?.hummock_sequences
};
Defensive patterns

Strategy: fallback

Validate before calling

// read header first and dispatch
let (format_version, _) = read_snapshot_header(&stream).await?;
if format_version < 2 { /* use full V1 decode path instead */ }

Type guard

fn supports_partial_decode(format_version: u32) -> bool { format_version >= 2 }

Try / catch

match decode_hummock_sequences_from_stream(stream).await {
    Ok(seqs) => seqs,
    Err(e) if e.to_string().contains("unsupported metadata snapshot format version") => {
        log::info!("legacy snapshot; using full decode path");
        decode_v1_full(stream).await?
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling decode_hummock_sequences_from_stream (directly or via load on a MetaSnapshot decoded as V2) on a snapshot whose header reports format_version 0 or 1.

Common situations: Restoring/inspecting a backup created by an old RisingWave version (pre-V2 snapshot format) with a current binary path that expects V2; a backup taken before the V2 migration; automated tooling assuming all snapshots are V2.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/storage/backup/src/meta_snapshot_v2.rs:155

    };
}

for_all_metadata_models_v2!(define_decode_metadata);

// Metadata V2 is encoded as a positional list of sections. The actual encoded order inserts
// `hummock_version` before `version_stats`, so `hummock_sequences` is section 26:
// 0 seaql_migrations, 1 hummock_version, 2 version_stats, ..., 26 hummock_sequences.
//
// Keep this as a fixed index so partial decoding can skip directly to `hummock_sequences`.
const HUMMOCK_SEQUENCES_METADATA_SECTION_INDEX: usize = 26;

pub async fn decode_hummock_sequences_from_stream(
    stream: MonitoredStreamingReader,
) -> BackupResult<Vec<risingwave_meta_model::hummock_sequence::Model>> {
    let mut reader = SnapshotPayloadReader::new(ObjectDataStreamReader::new(stream.into_stream()));
    let (format_version, _snapshot_id) = reader.read_snapshot_header().await?;
    if format_version < 2 {
        return Err(BackupError::Other(anyhow!(
            "unsupported metadata snapshot format version for hummock sequence partial decoding: {}",
            format_version
        )));
    }
    for _ in 0..HUMMOCK_SEQUENCES_METADATA_SECTION_INDEX {
        skip_metadata_list(&mut reader).await?;
    }
    let hummock_sequences = read_n(&mut reader).await?;
    reader.finish_after_skipping_to_end().await?;
    Ok(hummock_sequences)
}

impl Display for MetadataV2 {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        writeln!(f, "clusters: {:#?}", self.clusters)?;
        writeln!(
            f,
            "Hummock version: id {}, committed_epoch: {:?}",

View on GitHub (pinned to 6469eb736d)