{"record":{"id":"3dd5ea006af4375c","repo":"quickwit-oss/quickwit","slug":"invalid-recovery-time-range-start-start-is-afte","errorCode":null,"errorMessage":"invalid recovery time range: start {start} is after end {end}","messagePattern":"invalid recovery time range: start (.+?) is after end (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-metastore/src/split_metadata.rs","lineNumber":214,"sourceCode":"            node_id,\n            doc_mapping_uid,\n            partition_id,\n            num_docs,\n            uncompressed_docs_size_bytes,\n            time_range_start_inclusive,\n            time_range_end_inclusive,\n            create_timestamp,\n            tags,\n            delete_opstamp,\n            num_merge_ops,\n            parent_split_ids,\n            maturation_period_millis,\n        } = recovery_metadata;\n        let time_range = match (time_range_start_inclusive, time_range_end_inclusive) {\n            (Some(start), Some(end)) if start <= end => Some(start..=end),\n            (None, None) => None,\n            (Some(start), Some(end)) => {\n                bail!(\"invalid recovery time range: start {start} is after end {end}\")\n            }\n            _ => bail!(\"recovery time range must contain both start and end\"),\n        };\n        ensure!(\n            !footer_offsets.is_empty(),\n            \"invalid recovery footer offsets\"\n        );\n        let maturity = match maturation_period_millis {\n            Some(maturation_period_millis) => SplitMaturity::Immature {\n                maturation_period: Duration::from_millis(maturation_period_millis),\n            },\n            None => SplitMaturity::Mature,\n        };\n        let split_metadata = Self {\n            split_id: split_id.into(),\n            index_uid: index_uid.ok_or_else(|| anyhow::anyhow!(\"missing recovery index UID\"))?,\n            partition_id,\n            source_id,","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-metastore/src/split_metadata.rs#L196-L232","documentation":"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.","triggerScenarios":"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.","commonSituations":"Corrupted metastore rows after a crash; metadata files edited or copied between indexes with mismatched timestamps; clock-related data corruption.","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"],"exampleFix":"// before\n{\"time_range_start_inclusive\": 1700, \"time_range_end_inclusive\": 1600}\n// after\n{\"time_range_start_inclusive\": 1600, \"time_range_end_inclusive\": 1700}","handlingStrategy":"validation","validationCode":"fn time_range_valid(start: Option<i64>, end: Option<i64>) -> bool {\n    match (start, end) {\n        (Some(s), Some(e)) => s <= e,\n        (None, None) => true,\n        _ => false,\n    }\n}","typeGuard":"fn valid_range(m: &RecoveryMetadata) -> bool {\n    match (m.time_range_start_inclusive, m.time_range_end_inclusive) {\n        (Some(s), Some(e)) => s <= e,\n        (None, None) => true,\n        _ => false,\n    }\n}","tryCatchPattern":"match SplitMetadata::try_from(recovery_meta) {\n    Err(e) if e.to_string().contains(\"invalid recovery time range\") => {\n        error!(\"corrupted split metadata: {e}\");\n    }\n    other => other?,\n}","preventionTips":["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"],"tags":["metastore","split-metadata","time-range","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}