FuelLabs/fuel-core · critical · DatabaseError::RestoreError
Couldn't restore from latest backup for path `{}`: {}
Error message
Couldn't restore from latest backup for path `{}`: {} What it means
RestoreOptions-based restore_from_latest_backup failed for the target db path, wrapped as DatabaseError::RestoreError. Restoration copies the newest backup into db_dir/Description::name(); failure typically means there is no backup to restore from, the target directory is not usable, or the latest backup itself is damaged.
Source
Thrown at crates/fuel-core/src/state/rocks_db.rs:863
/// We delegate opening of restored db to consumer, so they can apply their own options
#[cfg(feature = "backup")]
pub fn restore<P: AsRef<Path> + ?Sized>(
db_dir: &P,
backup_dir: &P,
) -> DatabaseResult<()> {
use rocksdb::backup::RestoreOptions;
let mut backup_engine = Self::backup_engine(backup_dir)?;
let restore_option = RestoreOptions::default();
let db_dir = db_dir.as_ref().join(Description::name());
let db_dir_path = db_dir.as_path();
// we use the default wal directory, which is same as db path
backup_engine
.restore_from_latest_backup(db_dir_path, db_dir_path, &restore_option)
.map_err(|e| {
DatabaseError::RestoreError(anyhow::anyhow!(
"Couldn't restore from latest backup for path `{}`: {}",
db_dir_path.display(),
e
))
})?;
Ok(())
}
pub fn shutdown(&self) {
// Signal rocksdb's background compaction/flush threads to stop. We
// use `wait=false` so this returns immediately — each `CombinedDatabase`
// has several layered DBs and `wait=true` per-DB serialises into a
// shutdown that blows past tight per-service timeouts in tests
// (`tests/tests/poa.rs` budgets 1s for `send_stop_signal_and_await_shutdown`).
// The work is still cancelled; rocksdb's own destructor finishes the
// teardown when the last `Arc<PrimaryInstance>` clone is dropped.
self.db.cancel_all_background_work(false);View on GitHub (pinned to b9d4d170da)
Solutions
- Confirm the backup directory actually contains backups (backup_metadata and sst files) before restoring.
- Restore into an empty or removed target directory and stop the node first.
- Check permissions and free disk space on both source and target volumes.
- If the latest backup is corrupt, restore from an older backup id or create a fresh backup once the source is healthy.
Defensive patterns
Strategy: validation
Validate before calling
fn backup_exists(backup_dir: &std::path::Path, name: &str) -> bool {
let dir = backup_dir.join(name);
dir.join("backup_metadata").exists()
|| std::fs::read_dir(&dir).map(|mut d| d.next().is_some()).unwrap_or(false)
}
// before restore: require backup_exists(...) and an empty target dir Try / catch
match RocksDb::<Description>::restore(db_dir, backup_dir) {
Err(e) if e.to_string().contains("Couldn't restore from latest backup") => {
// verify a backup exists, clear/replace the target dir, check permissions, retry;
// if the latest backup is corrupt, fall back to an older backup
}
rest => rest,
} Prevention
- Verify backup contents (metadata plus sst files) before any restore drill.
- Always restore into an empty target directory with the node stopped.
- Periodically test restores; an untested backup is a hope, not a plan.
When it happens
Trigger: Calling restore with a backup directory that contains no backups (fresh or empty), a target directory with conflicting existing files, permission or disk problems, or a latest backup whose files were truncated by a crashed run.
Common situations: Disaster recovery pointed at the wrong backup directory; restoring over a live node's db directory; backups truncated by an interrupted earlier backup job.
Related errors
- Couldn't create backup engine options for path `{}`: {}
- Couldn't create environment for backup: {}
- Couldn't open backup engine for path `{}`: {}
- Couldn't create new backup for path `{}`: {}
- Not implemented yet
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/5b87539022650865.
Report an issue: GitHub.