diem/diem · error
Previous epoch ending LedgerInfo is not the one expected. My
Error message
Previous epoch ending LedgerInfo is not the one expected. My first epoch: {}, previous LedgerInfo next_block_epoch: {} What it means
The restore verifies continuity: the `next_block_epoch` of the previously restored epoch-ending LedgerInfo must equal the `first_epoch` in the backup manifest. If the epoch you are restoring from doesn't continue exactly where the local chain ends, this error fires with both epochs printed. It guards against restoring a backup that doesn't link to the existing database state.
Source
Thrown at storage/backup/backup-cli/src/backup_types/epoch_ending/restore.rs:219
}
}
impl PreheatedEpochEndingRestore {
async fn run_impl(
self,
previous_epoch_ending_ledger_info: Option<&LedgerInfo>,
) -> Result<Vec<LedgerInfo>> {
let preheat_data = self
.preheat_result
.map_err(|e| anyhow!("Preheat failed: {}", e))?;
let first_li = preheat_data
.ledger_infos
.first()
.expect("Epoch ending backup can't be empty.");
if let Some(li) = previous_epoch_ending_ledger_info {
ensure!(
li.next_block_epoch() == preheat_data.manifest.first_epoch,
"Previous epoch ending LedgerInfo is not the one expected. \
My first epoch: {}, previous LedgerInfo next_block_epoch: {}",
preheat_data.manifest.first_epoch,
li.next_block_epoch(),
);
// Waypoint has been verified in preheat if it's trusted, otherwise try to check
// the signatures.
if self
.controller
.trusted_waypoints
.get(&first_li.ledger_info().version())
.is_none()
{
li.next_epoch_state()
.ok_or_else(|| {
anyhow!("Previous epoch ending LedgerInfo doesn't end an epoch")
})?View on GitHub (pinned to fc4714a8ea)
Solutions
- Check the two printed epochs: the backup's first epoch must be exactly the previous LedgerInfo's next_block_epoch.
- Download and restore the missing/in-between epoch-ending backup so the chain is continuous.
- Confirm you are targeting the correct backup manifest handle for the epoch range that follows your current DB state.
- If the DB state is wrong/branchy, re-plan the restore from a known-good waypoint using the same chain's backups.
Example fix
// before: assuming any epoch-ending backup continues the chain
controller.preheat().await?.run(Some(&prev_li)).await?;
// after: check continuity first
let manifest = client.get_backup(backup_handle).await?;
assert_eq!(
prev_li.next_block_epoch(),
manifest.first_epoch,
"backup must start at epoch {}",
prev_li.next_block_epoch()
);
controller.preheat().await?.run(Some(&prev_li)).await?; Defensive patterns
Strategy: validation
Validate before calling
// before calling run, check epoch continuity
let manifest: EpochEndingBackup = client.get_backup(manifest_handle).await?;
if let Some(prev) = &prev_li {
ensure!(
prev.next_block_epoch() == manifest.first_epoch,
"need backup starting at epoch {}, got {}",
prev.next_block_epoch(),
manifest.first_epoch
);
} Try / catch
match restore.run(Some(&prev_li)).await {
Err(e) if e.to_string().contains("not the one expected") => {
// fetch the correct epoch-ending backup for prev_li.next_block_epoch()
Err(anyhow!("wrong backup selected: {}", e))
}
other => other,
} Prevention
- Always restore epoch-ending backups in strict epoch order, one per epoch, with no gaps.
- Derive the manifest handle programmatically from the current DB epoch rather than hardcoding it.
- Never mix backups from different chains/environments (mainnet vs testnet).
- Record and check the last restored epoch in a local checkpoint file between restore runs.
When it happens
Trigger: `run` called with `Some(&li)` where `li.next_block_epoch() != preheat_data.manifest.first_epoch` — e.g. wrong backup manifest handle selected, or the previous epoch-ending restore was skipped/overlapped.
Common situations: Restoring epoch-ending backups out of order or skipping one epoch; pointing the restore at a manifest from the wrong epoch range; mixing backups from different chains (e.g. testnet file into a mainnet DB); a previous restore that failed halfway leaving the DB at an unexpected epoch.
Related errors
- Previous epoch ending LedgerInfo doesn't end an epoch
- No waypoint in config
- Db-bootstrapper should not fail.
- State sync initialization failure
- Trying to generate waypoint at version {}, but DB has {} tra
AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04).
Data as JSON: /api/errors/8284c32c57e3cf41.
Report an issue: GitHub.