{"record":{"id":"5e897b8ea0d9d96a","repo":"rqlite/rqlite","slug":"no-snapshot-to-upgrade-in-old-snapshots-directory","errorCode":null,"errorMessage":"no snapshot to upgrade in old snapshots directory %s","messagePattern":"no snapshot to upgrade in old snapshots directory (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"snapshot/upgrader.go","lineNumber":92,"sourceCode":"\t\t\treturn fmt.Errorf(\"failed to remove old snapshot directory %s: %s\", old, err)\n\t\t}\n\t\tlogger.Printf(\"removed old snapshot directory %s as no upgrade is needed\", old)\n\t\treturn nil\n\t}\n\n\t// Start the upgrade process.\n\tif err := os.MkdirAll(newTmpDir, 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to create temporary snapshot directory %s: %s\", newTmpDir, err)\n\t}\n\n\toldMeta, err := getNewest7Snapshot(old)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get newest snapshot from old snapshots directory %s: %s\", old, err)\n\t}\n\tif oldMeta == nil {\n\t\t// No snapshot to upgrade, this shouldn't happen since we checked for an empty old\n\t\t// directory earlier.\n\t\treturn fmt.Errorf(\"no snapshot to upgrade in old snapshots directory %s\", old)\n\t}\n\n\t// Write out the new meta file in the new snapshot directory.\n\tnewSnapshotPath := filepath.Join(newTmpDir, oldMeta.ID)\n\tif err := os.MkdirAll(newSnapshotPath, 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to create new snapshot directory %s: %s\", newSnapshotPath, err)\n\t}\n\tif err := writeMeta(newSnapshotPath, oldMeta); err != nil {\n\t\treturn fmt.Errorf(\"failed to write new snapshot meta file to %s: %s\", newSnapshotPath, err)\n\t}\n\n\t// Ensure all file handles are closed before any directory is renamed or removed.\n\tif err := func() error {\n\t\t// Write SQLite database file into new snapshot dir.\n\t\tnewSqlitePath := filepath.Join(newTmpDir, oldMeta.ID+\".db\")\n\t\tnewSqliteFd, err := os.Create(newSqlitePath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create new SQLite file %s: %s\", newSqlitePath, err)","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/rqlite/rqlite/blob/7586a4d1bdbd9a5a80021664c5a863cd850adb60/snapshot/upgrader.go#L74-L110","documentation":"Upgrade7To8 found a non-empty old (v7) snapshots directory but getNewest7Snapshot returned no readable snapshot metadata, so there is nothing to upgrade. This is an internal-consistency violation: the earlier empty-directory check passed, yet no subdirectory contained a valid meta.json that could be parsed into Raft snapshot metadata. It signals that the old directory contains unexpected content or corrupted/partial snapshot directories.","triggerScenarios":"Calling snapshot.Upgrade7To8(old, new, logger) where 'old' is non-empty but every subdirectory either lacks meta.json, has a malformed/unparseable meta.json, or is not actually a v7 snapshot directory (readRaftMeta fails or is skipped via FileExists check).","commonSituations":"Upgrading a rqlite node from v7 to v8+ where the data directory was partially deleted, manually edited, or copied incompletely; stray non-snapshot subdirectories placed inside the snapshots path; leftover directories whose meta.json was lost after a crash or disk-full event.","solutions":["Inspect the old snapshots directory and confirm each subdirectory contains a valid meta.json; remove stray or corrupted subdirectories.","If the snapshots are not needed, delete or empty the old directory so Upgrade7To8 takes the clean empty-directory path.","Restore the node's data directory from a known-good backup or re-bootstrap/restore via /boot, since the snapshot store is unrecoverable as-is.","Check for a race where another process removed snapshot files while the upgrade was running; run the upgrade on a quiesced node."],"exampleFix":"// before (stray empty dir in old snapshots path blocks clean state)\n//  snapshots/v7/<stray-dir>/  (no meta.json)\n// after\n//  remove stray dirs so 'old' is either empty (clean skip) or contains only\n//  valid v7 snapshots: rm -rf /path/node/data/rsnapshots/v7/<stray-dir>","handlingStrategy":"validation","validationCode":"// Go: before relying on the upgrade path, verify the old dir holds valid v7 snapshots\nfunc hasValidV7Snapshot(dir string) bool {\n\tentries, err := os.ReadDir(dir)\n\tif err != nil { return false }\n\tfor _, e := range entries {\n\t\tif e.IsDir() && fsutil.FileExists(filepath.Join(dir, e.Name(), \"meta.json\")) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n// if dir exists, non-empty, and !hasValidV7Snapshot(dir): data dir is corrupt — restore before upgrading","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never manually add or edit files inside the rsnapshots directory.","After an unclean shutdown or disk-full event, validate snapshot directories before restarting an upgrade.","Keep backups of the whole data directory, not just meta files.","Stop rqlited before copying or pruning snapshot directories."],"tags":["filesystem","snapshot-migration","data-corruption","upgrade"],"backgroundTag":"snapshot-metadata-missing","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"}