influxdata/influxdb · error
invalid IOx metadata
Error message
invalid IOx metadata
What it means
TableMetaData::to_parquet_file converts an IoxParquetMetaData (thrift-encoded, zstd-compressed parquet footer bytes kept separate from the data) into catalog ParquetFileParams, and starts by calling metadata.decode().expect("invalid IOx metadata"). decode() is fallible; it fails when the stored metadata bytes are not valid IOx parquet metadata — corrupted objects, foreign parquet files, or bytes written by an incompatible IOx version.
Source
Thrown at core/parquet_file/src/metadata.rs:452
compaction_level: CompactionLevel::Initial,
sort_key: None,
max_l0_created_at: MaxL0CreatedAt::NotCompacted,
}
}
/// Create a corresponding iox catalog's ParquetFile
pub fn to_parquet_file<F>(
&self,
partition_id: PartitionId,
partition_hash_id: PartitionHashId,
file_size_bytes: u64,
metadata: &IoxParquetMetaData,
column_id_map: F,
) -> ParquetFileParams
where
F: for<'a> Fn(&'a str) -> ColumnId,
{
let decoded = metadata.decode().expect("invalid IOx metadata");
trace!(
?partition_id,
?decoded,
"DecodedIoxParquetMetaData decoded from its IoxParquetMetaData"
);
let row_count = decoded.row_count();
if decoded.md.row_groups().is_empty() {
debug!(
?partition_id,
"Decoded IoxParquetMetaData has no row groups to provide useful statistics"
);
}
// Derive the min/max timestamp from the Parquet column statistics.
let schema = decoded
.read_schema()
.expect("failed to read encoded schema");
let stats = decodedView on GitHub (pinned to d28e26e048)
Solutions
- Pre-validate before to_parquet_file: call metadata.decode() yourself (it returns Result) and handle the Err instead of letting the expect panic.
- Verify the object's integrity (size, checksum/ETag) against the catalog record to catch corruption/truncation.
- Confirm the file was written by the IOx write path with the same version; re-write or re-ingest foreign parquet files through IOx.
- File/track the upstream conversion expecting to take Result and propagate the error properly.
Example fix
// before
let params = table_meta.to_parquet_file(pid, phid, size, &iox_meta, &col_map); // panics via expect
// after
match iox_meta.decode() {
Ok(_) => table_meta.to_parquet_file(pid, phid, size, &iox_meta, &col_map),
Err(e) => {
tracing::error!(%e, "object has invalid IOx metadata; skipping");
return Err(e.into());
}
} Defensive patterns
Strategy: validation
Validate before calling
// pre-validate the metadata bytes before the panicking conversion
use parquet_file::metadata::IoxParquetMetaData;
fn metadata_decodes(m: &IoxParquetMetaData) -> bool {
m.decode().is_ok()
}
if !metadata_decodes(&iox_meta) {
return quarantine(object_store_id, "undecodable IOx metadata");
}
let params = table_meta.to_parquet_file(pid, phid, size, &iox_meta, col_map); Try / catch
// if you must call it on untrusted data, contain the panic and classify it
let params = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
table_meta.to_parquet_file(pid, phid, size, &iox_meta, &col_map)
}));
let params = match params {
Ok(p) => p,
Err(payload) => {
debug_assert_payload_mentions(&payload, "invalid IOx metadata");
return Err(CatalogError::InvalidParquetMetadata.into());
}
}; Prevention
- Treat to_parquet_file as trusting: only feed it metadata from objects you wrote via the IOx write path.
- Verify object size/checksum against the catalog before conversion to catch corruption early.
- Route external parquet through IOx ingest rather than direct catalog insertion.
- Track upstream migration of these expects to Result-returning APIs when upgrading.
When it happens
Trigger: Calling to_parquet_file on an IoxParquetMetaData whose bytes fail decoding: truncated/corrupted object-store payloads, parquet files produced by non-IOx writers (pandas/arrow/spark lack the IOx footer), or deserialization format changes between writer and reader versions.
Common situations: Catalog/compaction code loading files whose metadata blob was bit-rotted or partially written; ingesting externally-written parquet; upgrading IOx across a metadata encoding change; test fixtures with hand-built metadata bytes.
Related errors
- failed to read encoded schema
- invalid statistics
- no time column in metadata statistics
- no min time statistic
- num_row_groups_in_parallel should be above zero
AI-assisted analysis of influxdata/influxdb@d28e26e048 (2026-08-16).
Data as JSON: /api/errors/8bf33d932c7fccce.
Report an issue: GitHub.