{"record":{"id":"9d754def3a7cdaad","repo":"risingwavelabs/risingwave","slug":"invalid-epoch-range-start-epoch-end-epoch","errorCode":null,"errorMessage":"invalid epoch range: {start_epoch}..={end_epoch}","messagePattern":"invalid epoch range: (.+?)\\.\\.=(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/meta/src/hummock/error.rs","lineNumber":50,"sourceCode":"        #[source]\n        #[backtrace]\n        anyhow::Error,\n    ),\n    #[error(transparent)]\n    ObjectStore(\n        #[from]\n        #[backtrace]\n        ObjectError,\n    ),\n    #[error(\"compactor {0} is disconnected\")]\n    CompactorUnreachable(HummockContextId),\n    #[error(\"compaction group error: {0}\")]\n    CompactionGroup(String),\n    #[error(\"SST {0} is invalid\")]\n    InvalidSst(HummockSstableObjectId),\n    #[error(\"invalid manual compaction option: {0}\")]\n    InvalidManualCompactionOption(String),\n    #[error(\"invalid epoch range: {start_epoch}..={end_epoch}\")]\n    InvalidEpochRange { start_epoch: u64, end_epoch: u64 },\n    #[error(\"time-travel version expired: table {table_id}, epoch {epoch}\")]\n    TimeTravelVersionExpired { table_id: TableId, epoch: u64 },\n    #[error(\"time travel\")]\n    TimeTravel(\n        #[source]\n        #[backtrace]\n        anyhow::Error,\n    ),\n    #[error(transparent)]\n    Internal(\n        #[from]\n        #[backtrace]\n        anyhow::Error,\n    ),\n}\n\nimpl Error {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/hummock/error.rs#L32-L68","documentation":"HummockMetaError::InvalidEpochRange indicates an epoch range supplied to a Hummock operation is malformed — for example start_epoch greater than end_epoch, or a range that fails sanity checks. The message renders the exact start..=end range rejected.","triggerScenarios":"APIs taking an epoch range (e.g. time travel queries, version ranges, GC by epoch) receive start_epoch > end_epoch or otherwise invalid bounds.","commonSituations":"Computing epoch ranges from timestamps with incorrect ordering; off-by-one in epoch arithmetic; stale client caches producing inverted ranges; unit tests passing placeholder epochs.","solutions":["Ensure start_epoch <= end_epoch in the range being sent","Check the code that derives epochs from timestamps — fix ordering/inversion","Query current epoch (via meta) instead of using hardcoded or stale values","Log the originating range and clamp/swap it before calling the API"],"exampleFix":"// before\nlet (start_epoch, end_epoch) = (100, 50);\n// after\nlet (start_epoch, end_epoch) = (50, 100);\nassert!(start_epoch <= end_epoch);","handlingStrategy":"validation","validationCode":"if start_epoch > end_epoch {\n    return Err(anyhow!(\"invalid epoch range {}..={}\", start_epoch, end_epoch));\n}\n","typeGuard":"fn valid_epoch_range(start: u64, end: u64) -> bool { start <= end }\n","tryCatchPattern":"match op_with_epoch_range(start, end).await {\n    Err(HummockMetaError::InvalidEpochRange { start_epoch, end_epoch }) => {\n        eprintln!(\"fix range: start {start_epoch} must be <= end {end_epoch}\");\n    }\n    other => other?,\n}\n","preventionTips":["Always order epochs before constructing ranges","Derive epochs from a single authoritative source (meta current epoch)","Add assertions where ranges are built","Beware off-by-one when converting timestamps to epochs"],"tags":["rust","hummock","epoch","validation"],"backgroundTag":"invalid-argument-format","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}