risingwavelabs/risingwave · error · BackupError

metadata JSON payload length {} exceeds remaining buffer {}

Error message

metadata JSON payload length {} exceeds remaining buffer {}

What it means

This error is thrown when the declared length prefix of a metadata JSON payload is larger than the number of bytes left in the snapshot buffer, so skip_with_len_prefix_from_slice cannot advance past the payload. It means the snapshot payload is truncated or the length prefix was decoded from wrong bytes.

Source

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

                "metadata snapshot is truncated while reading u64"
            )));
        }
        Ok(buf.get_u64_le())
    }

    fn read_len_prefix_from_slice(buf: &mut &[u8]) -> BackupResult<usize> {
        match read_u32_le(buf)? {
            0 => read_u64_le(buf)?.try_into().map_err(|_| {
                BackupError::Other(anyhow!("metadata JSON payload length exceeds usize"))
            }),
            len => Ok(len as usize),
        }
    }

    fn skip_with_len_prefix_from_slice(buf: &mut &[u8]) -> BackupResult<()> {
        let len = read_len_prefix_from_slice(buf)?;
        if buf.remaining() < len {
            return Err(BackupError::Other(anyhow!(
                "metadata JSON payload length {} exceeds remaining buffer {}",
                len,
                buf.remaining()
            )));
        }
        buf.advance(len);
        Ok(())
    }

    fn skip_metadata_list_from_slice(buf: &mut &[u8]) -> BackupResult<()> {
        let n = read_u32_le(buf)? as usize;
        for _ in 0..n {
            skip_with_len_prefix_from_slice(buf)?;
        }
        Ok(())
    }

    fn put_with_len_prefix(buf: &mut Vec<u8>, data: &impl Serialize) {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Compare the buffer length with the expected snapshot size in the backup manifest and re-fetch the backup if short
  2. Fix upstream slice handling so reads/skips land on correct field boundaries before this call
  3. Validate the snapshot checksum before parsing to detect corruption early
Defensive patterns

Strategy: validation

Validate before calling

fn can_skip(buf: &[u8], prefix: &[u8]) -> bool {
    let p = u32::from_le_bytes(prefix[..4].try_into().unwrap()) as usize;
    p <= buf.len()
}

Try / catch

match skip_metadata_list_from_slice(&mut buf) {
    Err(e) if format!("{e:#}").contains("exceeds remaining buffer") => {
        // buffer truncated or misaligned: abort restore, verify checksum/size
    }
    other => other?,
}

Prevention

When it happens

Trigger: skip_metadata_list_from_slice skips an entry whose length prefix exceeds buf.remaining() — a truncated buffer, an oversized/corrupt length field, or prior misaligned reads inflating the declared length.

Common situations: Restoring from an incomplete backup upload; parsing a buffer that was sliced at the wrong offset; corrupted snapshot files after disk or network failures.

Related errors


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