quickwit-oss/quickwit · error · io::Error (InvalidData)
unsupported split fields format version: {version_byte[0]}
Error message
unsupported split fields format version: {version_byte[0]} What it means
ListFields-style split fields metadata is serialized with a single leading version byte. `deserialize` reads that byte and rejects any value other than FIELDS_METADATA_FORMAT_VERSION with InvalidData, since the rest of the wire format cannot be trusted to match the parser.
Source
Thrown at quickwit/quickwit-proto/src/search/mod.rs:256
impl ListFieldsMetadata {
/// Serializes the entries: one version byte followed by the zstd-compressed protobuf
/// encoding of `Self`.
pub fn serialize(&self) -> Vec<u8> {
let payload = self.encode_to_vec();
let mut out = vec![FIELDS_METADATA_FORMAT_VERSION];
zstd::stream::copy_encode(&payload[..], &mut out, FIELDS_METADATA_COMPRESSION_LEVEL)
.expect("zstd encoding into `Vec<u8>` should not fail");
out
}
/// Reads the format produced by [`Self::serialize`].
pub fn deserialize<R: Read>(mut reader: R) -> io::Result<Self> {
let mut version_byte = [0u8; 1];
reader.read_exact(&mut version_byte)?;
if version_byte[0] != FIELDS_METADATA_FORMAT_VERSION {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"unsupported split fields format version: {}",
version_byte[0]
),
));
}
let mut zstd_decoder = zstd::stream::read::Decoder::new(reader)?;
let mut decompressed = Vec::new();
zstd_decoder.read_to_end(&mut decompressed)?;
Self::decode(&decompressed[..])
.map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))
}
}
impl ListFieldsEntry {
pub fn cmp_by_name_and_type(&self, other: &Self) -> Ordering {View on GitHub (pinned to a39730c5cd)
Solutions
- Ensure the payload is the exact output of the matching SplitFieldsMetadata::serialize, version byte included.
- Use a Quickwit version compatible with the metadata format stored on the splits.
- Re-generate or re-index the splits whose metadata is in an unsupported format.
- Log/inspect the version byte value to identify the writer version.
Defensive patterns
Strategy: validation
Validate before calling
fn fields_version_ok(first_byte: u8) -> bool {
first_byte == FIELDS_METADATA_FORMAT_VERSION
} Try / catch
match SplitFieldsMetadata::deserialize(reader) {
Err(e) if e.to_string().contains("format version") => {
// incompatible writer version: re-index or migrate the split metadata
}
other => other?,
} Prevention
- Never strip the leading version byte when copying or transforming metadata payloads.
- Pin reader/writer to the same quickwit-proto version.
- Re-index splits whose metadata predates a format version bump.
When it happens
Trigger: Deserializing split fields metadata written by a different Quickwit version (different FIELDS_METADATA_FORMAT_VERSION), or feeding deserialize a payload without the version prefix (e.g. the raw zstd/protobuf body).
Common situations: Upgrading/downgrading Quickwit while old splits' field metadata persists in storage; manually reassembling the payload and dropping the version byte; writing custom tooling against the metadata format.
Related errors
- unsupported split recovery metadata format version: {version
- invalid split recovery metadata magic number
- unsupported split recovery metadata format version: {version
- dynamic protobuf decode error wrapped as io::Error (InvalidD
- `doc_batch` should not be empty
AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08).
Data as JSON: /api/errors/e0f5161390896143.
Report an issue: GitHub.