{"record":{"id":"9738c09b27dc508e","repo":"rqlite/rqlite","slug":"failed-to-move-temporary-snapshot-directory-s-to","errorCode":null,"errorMessage":"failed to move temporary snapshot directory %s to %s: %s","messagePattern":"failed to move temporary snapshot directory (.+?) to (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"snapshot/upgrader.go","lineNumber":162,"sourceCode":"\t\t\t\t\tnewSqlitePath, err)\n\t\t\t}\n\t\t\tif !db.IsValidSQLiteFile(newSqlitePath) {\n\t\t\t\treturn fmt.Errorf(\"migrated SQLite file %s is not valid\", newSqlitePath)\n\t\t\t}\n\t\t}\n\n\t\t// Ensure database file exists and convert to WAL mode.\n\t\tif err := db.EnsureWALMode(newSqlitePath); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to convert migrated SQLite file %s to WAL mode: %s\", newSqlitePath, err)\n\t\t}\n\t\treturn nil\n\t}(); err != nil {\n\t\treturn err\n\t}\n\n\t// Move the upgraded snapshot directory into place.\n\tif err := os.Rename(newTmpDir, new); err != nil {\n\t\treturn fmt.Errorf(\"failed to move temporary snapshot directory %s to %s: %s\", newTmpDir, new, err)\n\t}\n\tif err := fsutil.SyncDirParentMaybe(new); err != nil {\n\t\treturn fmt.Errorf(\"failed to sync parent directory of new snapshot directory %s: %s\", new, err)\n\t}\n\n\t// We're done! Remove old.\n\tif err := fsutil.RemoveDirSync(old); err != nil {\n\t\treturn fmt.Errorf(\"failed to remove old snapshot directory %s: %s\", old, err)\n\t}\n\tlogger.Printf(\"upgraded v7 snapshot directory %s to %s\", old, new)\n\tstats.Add(upgradeOk, 1)\n\n\treturn nil\n}\n\n// Upgrade8To10 writes a copy of the 8.x-format Snapshot directory at 'old' to a\n// 10.x-format Snapshot directory at 'new'. In v8 format, the SQLite database file\n// is stored at the root of the snapshot directory as '<id>.db', alongside a snapshot","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/rqlite/rqlite/blob/7586a4d1bdbd9a5a80021664c5a863cd850adb60/snapshot/upgrader.go#L144-L180","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","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"],"exampleFix":"// before: leftover dir from a crashed upgrade blocks rename\n$ ls data/snapshots  # new/ already exists with junk\n// after\n$ rm -rf data/snapshots/new && systemctl restart rqlited  # old v7 dir still present, upgrade retried","handlingStrategy":"validation","validationCode":"// pre-flight: target must not exist, parent must be writable, same filesystem\nif _, err := os.Stat(new); err == nil {\n    return fmt.Errorf(\"target snapshot dir %s already exists; clean up prior failed upgrade first\", new)\n}\nif unix.Access(filepath.Dir(new), unix.W_OK) != nil {\n    return fmt.Errorf(\"parent of %s not writable\", new)\n}","typeGuard":null,"tryCatchPattern":"if err := snapshot.Upgrade7To8(old, new, logger); err != nil {\n    if strings.Contains(err.Error(), \"failed to move temporary snapshot directory\") {\n        // old v7 dir still intact; resolve EXDEV/EEXIST then retry safely\n    }\n}","preventionTips":["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"],"tags":["filesystem","snapshot-upgrade","rename","permissions"],"backgroundTag":"rename-failed","analyzedSha":"7586a4d1bdbd9a5a80021664c5a863cd850adb60","analyzedAt":"2026-09-03T07:03:02.260Z","contentChangedAt":"2026-09-03T07:03:02.260Z","schemaVersion":2},"datasetVersion":"2026-09-10T12:17:11.382Z"}