{"record":{"id":"fe7de6cc0eb770ff","repo":"risingwavelabs/risingwave","slug":"since-timestamp-is-later-than-the-latest-changelog","errorCode":null,"errorMessage":"since_timestamp is later than the latest changelog of upstream table {}: requested epoch {}, latest changelog epoch {}","messagePattern":"since_timestamp is later than the latest changelog of upstream table (.+?): requested epoch (.+?), latest changelog epoch (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/meta/src/barrier/context/context_impl.rs","lineNumber":120,"sourceCode":"        )\n        .into());\n    }\n\n    // `binary_search_by_checkpoint_epoch` searches only by the checkpoint epoch\n    // of each changelog entry. An entry may still cover earlier non-checkpoint\n    // epochs, e.g. `{ non_checkpoint_epochs: [30, 35], checkpoint_epoch: 40 }`\n    // covers `(20, 40]` if the previous checkpoint is 20. For `since_epoch =\n    // 35`, the search returns `Err(index_of_40)`, and 40 is the snapshot epoch.\n    // For `since_epoch = 40`, it returns `Ok(index_of_40)`. In both cases, the\n    // resolved snapshot epoch is the least checkpoint epoch >= `since_epoch`.\n    let snapshot_epoch_index = match change_log.binary_search_by_checkpoint_epoch(since_epoch) {\n        Ok(index) => index,\n        Err(index) => index,\n    };\n    let snapshot_epoch = change_log\n        .get(snapshot_epoch_index)\n        .ok_or_else(|| {\n            anyhow::anyhow!(\n                \"since_timestamp is later than the latest changelog of upstream table {}: requested epoch {}, latest changelog epoch {}\",\n                table_id,\n                since_epoch,\n                upstream_committed_epoch,\n            )\n        })?\n        .checkpoint_epoch;\n    // A request inside the latest changelog entry may be smaller than\n    // `upstream_committed_epoch`, but still resolve to the latest checkpoint.\n    // That end-of-log case is not a usable historical snapshot epoch.\n    if snapshot_epoch >= upstream_committed_epoch {\n        return Err(anyhow::anyhow!(\n            \"since_timestamp is too new for upstream table {}: requested epoch {}, resolved snapshot epoch {}, latest changelog epoch {}\",\n            table_id,\n            since_epoch,\n            snapshot_epoch,\n            upstream_committed_epoch,\n        )","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/barrier/context/context_impl.rs#L102-L138","documentation":"Binary search over the changelog failed to find a change-log entry at the target epoch, so the resolved snapshot epoch index is out of bounds. This indicates the requested epoch is beyond the latest retained changelog entry.","triggerScenarios":"resolve_since_timestamp_log_store_epoch when the computed snapshot_epoch_index is >= change_log.len() (since_epoch later than all retained changelog entries), making change_log.get(index) return None.","commonSituations":"Since timestamp newer than the latest changelog entry due to clock skew; changelog trimmed; race where the barrier state changelog is stale relative to the caller's epoch.","solutions":["Use a since_timestamp within the retained changelog range","Retry after the next barrier refreshes the changelog","Check retention configuration and upstream progress","Report a bug if the epoch was validated as within range beforehand"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let idx = search_index(change_log, since_epoch);\nif idx >= change_log.len() {\n    return Err(\"since_timestamp beyond latest retained changelog entry\");\n}","typeGuard":"fn index_in_bounds(log: &TableChangeLog, idx: usize) -> bool { idx < log.len() }","tryCatchPattern":"match create_snapshot_backfill(...).await {\n    Err(e) if e.contains(\"later than the latest changelog\") => retry_after_next_barrier(),\n    other => other,\n}","preventionTips":["Keep since_epoch within [first, last] changelog checkpoints","Refresh barrier state before resolution","Watch for clock skew making timestamps too new"],"tags":["meta","barrier","changelog","since-timestamp"],"backgroundTag":"index-out-of-bounds","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"}