quickwit-oss/quickwit · error
invalid recovery time range: start {start} is after end {end
Error message
invalid recovery time range: start {start} is after end {end} What it means
Thrown by try_from_recovery_metadata when a split's recovery metadata has both a start and an end timestamp but start > end, making the inclusive time range unconstructible. The code only accepts a valid ordered range or a fully absent one.
Source
Thrown at quickwit/quickwit-metastore/src/split_metadata.rs:214
node_id,
doc_mapping_uid,
partition_id,
num_docs,
uncompressed_docs_size_bytes,
time_range_start_inclusive,
time_range_end_inclusive,
create_timestamp,
tags,
delete_opstamp,
num_merge_ops,
parent_split_ids,
maturation_period_millis,
} = recovery_metadata;
let time_range = match (time_range_start_inclusive, time_range_end_inclusive) {
(Some(start), Some(end)) if start <= end => Some(start..=end),
(None, None) => None,
(Some(start), Some(end)) => {
bail!("invalid recovery time range: start {start} is after end {end}")
}
_ => bail!("recovery time range must contain both start and end"),
};
ensure!(
!footer_offsets.is_empty(),
"invalid recovery footer offsets"
);
let maturity = match maturation_period_millis {
Some(maturation_period_millis) => SplitMaturity::Immature {
maturation_period: Duration::from_millis(maturation_period_millis),
},
None => SplitMaturity::Mature,
};
let split_metadata = Self {
split_id: split_id.into(),
index_uid: index_uid.ok_or_else(|| anyhow::anyhow!("missing recovery index UID"))?,
partition_id,
source_id,View on GitHub (pinned to a39730c5cd)
Solutions
- Fix the offending split metadata so start <= end, or remove the time range entirely (both fields None)
- Delete/re-ingest the affected split so new metadata is generated
- Restore the metastore data from backup
Example fix
// before
{"time_range_start_inclusive": 1700, "time_range_end_inclusive": 1600}
// after
{"time_range_start_inclusive": 1600, "time_range_end_inclusive": 1700} Defensive patterns
Strategy: validation
Validate before calling
fn time_range_valid(start: Option<i64>, end: Option<i64>) -> bool {
match (start, end) {
(Some(s), Some(e)) => s <= e,
(None, None) => true,
_ => false,
}
} Type guard
fn valid_range(m: &RecoveryMetadata) -> bool {
match (m.time_range_start_inclusive, m.time_range_end_inclusive) {
(Some(s), Some(e)) => s <= e,
(None, None) => true,
_ => false,
}
} Try / catch
match SplitMetadata::try_from(recovery_meta) {
Err(e) if e.to_string().contains("invalid recovery time range") => {
error!("corrupted split metadata: {e}");
}
other => other?,
} Prevention
- Never manually edit split metadata timestamps
- Validate start <= end when generating recovery metadata programmatically
- Restore corrupted metastore records from backups rather than patching by hand
When it happens
Trigger: Loading or converting split metadata whose recovery metadata contains time_range_start_inclusive > time_range_end_inclusive, typically from corrupted or externally modified metadata records.
Common situations: Corrupted metastore rows after a crash; metadata files edited or copied between indexes with mismatched timestamps; clock-related data corruption.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- recovery time range must contain both start and end
- missing recovery index UID
- missing recovery doc mapping UID
- {left:?} metastore config is defined multiple times
- the `metastore_read_replica` service must run standalone and
AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08).
Data as JSON: /api/errors/3dd5ea006af4375c.
Report an issue: GitHub.