{"record":{"id":"bc74f16ff9ee1612","repo":"can1357/oh-my-pi","slug":"backup-not-found-backuppath","errorCode":null,"errorMessage":"Backup not found: ${backupPath}","messagePattern":"Backup not found: (.+?)","errorType":"exception","errorClass":"FileNotFoundError","httpStatus":null,"severity":"error","filePath":"packages/mnemopi/src/dr/recovery.ts","lineNumber":250,"sourceCode":"\tfor (const suffix of SQLITE_SIDECAR_SUFFIXES) {\n\t\tconst sidecar = sqliteSidecarPath(targetPath, suffix);\n\t\trmSync(sidecar, { force: true });\n\t\tconst backupSidecar = emergencyBackupSidecarPath(targetPath, suffix);\n\t\tif (existsSync(backupSidecar)) copyFileSync(backupSidecar, sidecar);\n\t}\n}\n\nfunction writeRestoreCandidate(uncompressed: Buffer, tempPath: string): void {\n\tif (isSqliteFile(uncompressed)) {\n\t\twriteFileSync(tempPath, uncompressed, { flag: \"wx\" });\n\t\treturn;\n\t}\n\twriteGzippedSqlDump(uncompressed.toString(\"utf8\"), tempPath);\n}\n\nexport function restoreBackup(backupPath: string, dbPath?: string | null): RestoreResult {\n\tconst targetPath = dbPath ?? getDefaultPaths().dbPath;\n\tif (!existsSync(backupPath)) throw new FileNotFoundError(`Backup not found: ${backupPath}`);\n\n\tmkdirSync(dirname(targetPath), { recursive: true });\n\n\tconst uncompressed = gunzipSync(readFileSync(backupPath));\n\tconst tempPath = restoreTempPath(targetPath);\n\tlet replacedTarget = false;\n\ttry {\n\t\twriteRestoreCandidate(uncompressed, tempPath);\n\t\tif (!verifyIntegrity(tempPath)) throw new Error(`Backup failed integrity check: ${backupPath}`);\n\t\tsnapshotCurrentDatabase(targetPath);\n\t\trenameSync(tempPath, targetPath);\n\t\treplacedTarget = true;\n\t\tremoveSqliteSidecars(targetPath);\n\t\tconst integrity = verifyIntegrity(targetPath);\n\t\tif (!integrity) throw new Error(`Restored database failed integrity check: ${backupPath}`);\n\t\treturn {\n\t\t\trestored: true,\n\t\t\tbackup_used: backupPath,","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/mnemopi/src/dr/recovery.ts#L232-L268","documentation":"restoreBackup checks that the given backup file exists before decompressing and replacing the live database, throwing FileNotFoundError when backupPath doesn't exist. This prevents silently restoring from a missing file and destroying the current db with nothing.","triggerScenarios":"restoreBackup(path) with a typo'd path or a backup that was deleted/rotated away; pointing at a backup in another directory; running restore before any backup was created; the backup job failed earlier so the expected file never appeared.","commonSituations":"Cleanup jobs pruning old backups that are still referenced; path built from a timestamp string with a typo; cross-machine restore where the file wasn't transferred; expecting default backup dir contents on a fresh machine.","solutions":["Verify the backup path exists (ls the backup directory) and pass the correct path to restoreBackup","Create a fresh backup with createBackup first if none exists","Check rotation/cleanup configuration so needed backups aren't deleted"],"exampleFix":"// before\nrestoreBackup(\"/backups/memory-2026-08-31.gz\"); // never created\n// after\nconst backupPath = \"/backups/memory-2026-08-31.gz\";\nif (!existsSync(backupPath)) {\n\t({ backupPath } = createBackup(dbPath, \"/backups\"));\n}\nrestoreBackup(backupPath);","handlingStrategy":"validation","validationCode":"import { existsSync } from \"node:fs\";\nfunction safeRestore(backupPath, dbPath) {\n\tif (!existsSync(backupPath)) throw new Error(`backup missing: ${backupPath}`);\n\treturn restoreBackup(backupPath, dbPath);\n}","typeGuard":null,"tryCatchPattern":"try {\n\trestoreBackup(backupPath, dbPath);\n} catch (err) {\n\tif (err.name === \"FileNotFoundError\" && err.message.startsWith(\"Backup not found\")) {\n\t\tconst available = readdirSync(backupDir);\n\t\tthrow new Error(`backup not found; available: ${available.join(\", \")}`, { cause: err });\n\t}\n\tthrow err;\n}","preventionTips":["List the backup directory and pick an existing file rather than guessing timestamps","Confirm backup jobs succeeded before relying on their output","Transfer/copy backups to the restore host first","Keep rotation policies aligned with restore expectations"],"tags":["filesystem","restore","file-not-found"],"backgroundTag":"file-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}