risingwavelabs/risingwave · error · TimeTravel
prev_version {} not found
Error message
prev_version {} not found What it means
During time-travel metadata truncation, each previous-version ID planned for deletion is looked up in the hummock_time_travel_version table inside the transaction. If find_by_id returns no row, the code returns Error::TimeTravel("prev_version {} not found") — a lookup failure indicating the version row is missing while the deletion plan still references it.
Source
Thrown at src/meta/src/hummock/manager/time_travel.rs:343
if sst_ids_to_delete.len() >= delete_sst_batch_size {
delete_sst_in_batch(
&txn,
std::mem::take(&mut sst_ids_to_delete),
delete_sst_batch_size,
)
.await?;
}
let new_object_ids = delta_to_delete.newly_added_object_ids();
object_ids_to_delete.extend(&new_object_ids - &retained_snapshot_object_ids);
}
}
for prev_version_id in version_ids_to_delete {
let prev_version = {
let prev_version = hummock_time_travel_version::Entity::find_by_id(prev_version_id)
.one(&txn)
.await?
.ok_or_else(|| {
Error::TimeTravel(anyhow!(format!(
"prev_version {} not found",
prev_version_id
)))
})?;
IncompleteHummockVersion::from_persisted_protobuf_owned(
prev_version.version.to_protobuf(),
)
};
let sst_ids = prev_version.get_sst_ids();
sst_ids_to_delete.extend(&sst_ids - &retained_snapshot_sst_ids);
if sst_ids_to_delete.len() >= delete_sst_batch_size {
delete_sst_in_batch(
&txn,
std::mem::take(&mut sst_ids_to_delete),
delete_sst_batch_size,
)
.await?;
}View on GitHub (pinned to 6469eb736d)
Solutions
- Check the hummock_time_travel_version table for the reported version id to confirm it is genuinely missing.
- Prevent concurrent time-travel GC from running in parallel; run a single GC coordinator.
- Restore meta store consistency from a backup or rebuild time-travel metadata if rows are missing.
- File a bug with logs and the version id — a missing row here usually signals an internal consistency bug.
Defensive patterns
Strategy: try-catch
Validate before calling
// verify prev-version rows exist before planning deletion
let existing: HashSet<_> = version_ids_to_delete.iter()
.filter(|id| version_exists_in_store(id))
.cloned().collect();
let dangling: Vec<_> = version_ids_to_delete.difference(&existing).collect();
if !dangling.is_empty() { /* abort: inconsistent metadata */ } Try / catch
// catch the typed error and treat as consistency alarm
match meta.delete_time_travel_metadata(...).await {
Err(Error::TimeTravel(e)) if e.to_string().contains("prev_version") => {
// halt GC, snapshot meta store state for diagnosis
}
other => other,
} Prevention
- Serialize time-travel metadata deletion; forbid parallel GC tasks.
- Do not hand-edit hummock_time_travel_version rows.
- Restore the meta store from a single consistent backup snapshot.
- Log and report occurrences — usually an internal bug worth filing upstream.
When it happens
Trigger: Calling delete_time_travel_metadata when a hummock_time_travel_version row for prev_version_id was already removed (concurrent truncation, manual DB cleanup) or the pinning/version snapshot lists versions that no longer exist in the store.
Common situations: Racing version GC workers; manual deletes against the meta store database; corrupted or partially restored meta store after a crash or restore operation.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- version delta {} not found
- too many inflight time travel queries, max_inflight_time_tra
- time-travel version expired: table {table_id}, epoch {epoch}
- time travel
- object {object_id} is rejected from being committed since it
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/ebfe8492671c7c58.
Report an issue: GitHub.