can1357/oh-my-pi · critical · Error

Restored database failed integrity check: ${backupPath}

Error message

Restored database failed integrity check: ${backupPath}

What it means

After restoreBackup() atomically renames the verified candidate over the live database and removes SQLite sidecar files, it runs verifyIntegrity() once more on the installed file. If the restored database at targetPath still fails the integrity check, it throws this error. Unlike the pre-check failure, the live database has already been replaced at this point, so the snapshot taken by snapshotCurrentDatabase() is the recovery path.

Source

Thrown at packages/mnemopi/src/dr/recovery.ts:265

export function restoreBackup(backupPath: string, dbPath?: string | null): RestoreResult {
	const targetPath = dbPath ?? getDefaultPaths().dbPath;
	if (!existsSync(backupPath)) throw new FileNotFoundError(`Backup not found: ${backupPath}`);

	mkdirSync(dirname(targetPath), { recursive: true });

	const uncompressed = gunzipSync(readFileSync(backupPath));
	const tempPath = restoreTempPath(targetPath);
	let replacedTarget = false;
	try {
		writeRestoreCandidate(uncompressed, tempPath);
		if (!verifyIntegrity(tempPath)) throw new Error(`Backup failed integrity check: ${backupPath}`);
		snapshotCurrentDatabase(targetPath);
		renameSync(tempPath, targetPath);
		replacedTarget = true;
		removeSqliteSidecars(targetPath);
		const integrity = verifyIntegrity(targetPath);
		if (!integrity) throw new Error(`Restored database failed integrity check: ${backupPath}`);
		return {
			restored: true,
			backup_used: backupPath,
			database_path: targetPath,
			integrity_check: integrity,
		};
	} catch (error) {
		try {
			rmSync(tempPath, { force: true });
		} catch {
			// Preserve the restore failure.
		}
		if (replacedTarget) {
			try {
				restoreCurrentDatabaseSnapshot(targetPath);
			} catch {
				// Preserve the restore failure.
			}

View on GitHub (pinned to 9690622007)

Solutions

  1. Restore the pre-restore snapshot created by snapshotCurrentDatabase() back over targetPath.
  2. Close all processes holding targetPath open, delete any residual -wal/-shm files, and rerun restoreBackup().
  3. Run `sqlite3 targetPath 'PRAGMA integrity_check;'` to inspect the damage and attempt `.recover` to salvage data.
  4. Check filesystem health (dmesg, fsck) — repeated post-rename corruption usually indicates hardware/storage failure.

Example fix

// before
const result = restoreBackup(backupPath, dbPath);
// after
try {
  const result = restoreBackup(backupPath, dbPath);
} catch (err) {
  if (String(err).includes('Restored database failed integrity check')) {
    const snapshot = findLatestSnapshot(dbPath); // file written by snapshotCurrentDatabase
    copyFileSync(snapshot, dbPath);
    console.error('Restored snapshot; investigate storage health');
  }
  throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure no other process holds the target open and no stale sidecars exist before restoring:
import { existsSync, unlinkSync } from 'node:fs';
for (const suffix of ['-wal', '-shm', '-journal']) {
  const sidecar = targetPath + suffix;
  if (existsSync(sidecar)) unlinkSync(sidecar);
}

Type guard

function restoreSucceeded(r) {
  return r != null && r.restored === true && r.integrity_check === true;
}

Try / catch

try {
  const result = restoreBackup(backupPath, targetPath);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Restored database failed integrity check')) {
    restoreSnapshot(targetPath); // snapshotCurrentDatabase wrote one before the rename
  }
  throw err;
}

Prevention

When it happens

Trigger: verifyIntegrity(targetPath) returns false after renameSync(tempPath, targetPath) and removeSqliteSidecars(targetPath) — i.e. the post-rename on-disk state is corrupt even though the temp candidate passed.

Common situations: Failing disk/filesystem corruption during rename, leftover stale -wal/-shm sidecars interfering, another process writing to targetPath mid-restore, or filesystems without atomic rename semantics (some network mounts).

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/0dec715a63d034bf. Report an issue: GitHub.