quickwit-oss/quickwit · error

unsupported split footer trailer version

Error message

unsupported split footer trailer version {version}

What it means

Split files end with a footer trailer containing a version number alongside the footer start offset. deserialize_split_footer_trailer rejects trailers whose version differs from SPLIT_FOOTER_TRAILER_VERSION, since the layout cannot be interpreted across incompatible versions. This protects readers from misparsing splits written by incompatible Quickwit versions.

Solutions

  1. Upgrade Quickwit to the version that wrote the splits (check the trailer version against release notes).
  2. Avoid downgrading a cluster that already contains splits written by a newer version.
  3. Re-index the affected splits into a format the current version supports if upgrading is impossible.
Defensive patterns

Strategy: fallback

Try / catch

match locate_split_footer_range(split, &storage).await {
    Ok(footer) => footer,
    Err(e) if e.to_string().contains("unsupported split footer trailer version") => {
        // re-index the split with a compatible version, or fail with a clear upgrade message
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Reading a split whose footer trailer version field differs from the version the current binary expects — i.e. the split was written by a newer or otherwise incompatible Quickwit release.

Common situations: Rolling upgrades where a newer writer version created splits before the cluster was fully upgraded; downgrading Quickwit below the version that wrote the splits; corrupted trailer bytes flipping the version field.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/f8b07936c9c79119. Report an issue: GitHub.

Appendix: source

Thrown at quickwit/quickwit-storage/src/bundle_storage.rs:190

    writer.put_u64_le(footer_start_inclusive);
    writer.put_u32_le(SPLIT_FOOTER_TRAILER_VERSION);
    writer.put_slice(SPLIT_FOOTER_TRAILER_MAGIC);
    debug_assert!(!writer.has_remaining_mut());
    trailer
}

fn deserialize_split_footer_trailer(trailer: &[u8]) -> anyhow::Result<Option<u64>> {
    if trailer.len() != SPLIT_FOOTER_TRAILER_NUM_BYTES {
        return Ok(None);
    }
    let mut reader = trailer;
    let footer_start_inclusive = reader.get_u64_le();
    let version = reader.get_u32_le();

    if reader != SPLIT_FOOTER_TRAILER_MAGIC {
        return Ok(None);
    }
    ensure!(
        version == SPLIT_FOOTER_TRAILER_VERSION,
        "unsupported split footer trailer version {version}"
    );
    Ok(Some(footer_start_inclusive))
}

/// Locates a split footer range using its fixed trailer, with support for legacy split layouts.
pub async fn locate_split_footer_range(
    storage: &dyn Storage,
    split_path: &Path,
    split_len: u64,
) -> anyhow::Result<Range<u64>> {
    ensure!(
        split_len >= SPLIT_FOOTER_TRAILER_NUM_BYTES as u64,
        "split is too short to contain a footer"
    );
    let end = split_len as usize;
    let start = end - SPLIT_FOOTER_TRAILER_NUM_BYTES;

View on GitHub (pinned to a39730c5cd)