rqlite/rqlite · error
failed to move temporary snapshot directory %s to %s: %s
Error message
failed to move temporary snapshot directory %s to %s: %s
What it means
Upgrade7To8 wraps os.Rename failing when atomically moving the completed temporary upgrade directory into its final location. All data migration succeeded; only the final atomic swap failed. The old v7 directory is intentionally left in place so the upgrade can be retried.
Source
Thrown at snapshot/upgrader.go:162
newSqlitePath, err)
}
if !db.IsValidSQLiteFile(newSqlitePath) {
return fmt.Errorf("migrated SQLite file %s is not valid", newSqlitePath)
}
}
// Ensure database file exists and convert to WAL mode.
if err := db.EnsureWALMode(newSqlitePath); err != nil {
return fmt.Errorf("failed to convert migrated SQLite file %s to WAL mode: %s", newSqlitePath, err)
}
return nil
}(); err != nil {
return err
}
// Move the upgraded snapshot directory into place.
if err := os.Rename(newTmpDir, new); err != nil {
return fmt.Errorf("failed to move temporary snapshot directory %s to %s: %s", newTmpDir, new, err)
}
if err := fsutil.SyncDirParentMaybe(new); err != nil {
return fmt.Errorf("failed to sync parent directory of new snapshot directory %s: %s", new, err)
}
// We're done! Remove old.
if err := fsutil.RemoveDirSync(old); err != nil {
return fmt.Errorf("failed to remove old snapshot directory %s: %s", old, err)
}
logger.Printf("upgraded v7 snapshot directory %s to %s", old, new)
stats.Add(upgradeOk, 1)
return nil
}
// Upgrade8To10 writes a copy of the 8.x-format Snapshot directory at 'old' to a
// 10.x-format Snapshot directory at 'new'. In v8 format, the SQLite database file
// is stored at the root of the snapshot directory as '<id>.db', alongside a snapshotView on GitHub (pinned to 7586a4d1bd)
Solutions
- Check whether the 'new' snapshots directory already exists and is non-empty; if it is a leftover from a crashed upgrade and is incomplete, remove it and restart (the old v7 dir is still intact)
- Ensure the parent of 'new' is writable by the rqlited user (ls -ld, chown)
- Ensure the snapshot store's temp dir and target dir are on the same filesystem
- Restart rqlited to retry the idempotent upgrade
Example fix
// before: leftover dir from a crashed upgrade blocks rename $ ls data/snapshots # new/ already exists with junk // after $ rm -rf data/snapshots/new && systemctl restart rqlited # old v7 dir still present, upgrade retried
Defensive patterns
Strategy: validation
Validate before calling
// pre-flight: target must not exist, parent must be writable, same filesystem
if _, err := os.Stat(new); err == nil {
return fmt.Errorf("target snapshot dir %s already exists; clean up prior failed upgrade first", new)
}
if unix.Access(filepath.Dir(new), unix.W_OK) != nil {
return fmt.Errorf("parent of %s not writable", new)
} Try / catch
if err := snapshot.Upgrade7To8(old, new, logger); err != nil {
if strings.Contains(err.Error(), "failed to move temporary snapshot directory") {
// old v7 dir still intact; resolve EXDEV/EEXIST then retry safely
}
} Prevention
- Keep the entire rqlite data tree on a single filesystem
- After a crashed upgrade, check for and clean leftover target directories before restarting
- Ensure consistent ownership of the data directory across restarts/containers
When it happens
Trigger: Calling Upgrade7To8 when rename(newTmpDir, new) fails — target path already exists and is a non-empty directory (EXDEV aside, rename of a directory onto an existing non-empty dir fails), newTmpDir and new on different filesystems (EXDEV), or permission problems on the parent of 'new'.
Common situations: A previous crashed upgrade left the 'new' directory partially populated; data directory split across mounts; rqlited restarted over a directory with wrong ownership; container volume setups with different filesystems for tmp vs data.
Related errors
- failed to rename temporary metadata file %s to %s: %w
- failed to check if old snapshot directory %s is empty: %s
- failed to remove empty old snapshot directory %s: %s
- failed to remove old snapshot directory %s: %s
- failed to move %s after recovery: %s
AI-assisted analysis of rqlite/rqlite@7586a4d1bd (2026-09-03).
Data as JSON: /api/errors/9738c09b27dc508e.
Report an issue: GitHub.