Yeachan-Heo/oh-my-codex · error · Error

Native hook transaction backup verification failed for ${bac

Error message

Native hook transaction backup verification failed for ${backupPath}.

What it means

As the last step of backup verification, setup reads the backup file back and compares bytes to what was written. A byte-level mismatch means the on-disk backup does not faithfully represent the pre-transaction state, so the transaction is aborted rather than proceed with an unusable backup.

Source

Thrown at src/cli/setup.ts:2006

				if (createdStat.isSymbolicLink() || !createdStat.isDirectory()) {
					throw new Error(`Refusing to use unsafe created backup ancestor ${currentPath}.`);
				}
			}
		}
		const handle = await open(backupPath, "wx", 0o600);
		try {
			await handle.writeFile(bytes);
			recordRegularFileSyncOutcome(tracker, await syncNativeHookRegularFile(handle));
		} finally {
			await handle.close();
		}
		const backupStat = await lstat(backupPath);
		if (backupStat.isSymbolicLink() || !backupStat.isFile() || backupStat.nlink !== 1) {
			throw new Error(`Refusing unsafe native hook transaction backup ${backupPath}.`);
		}
		const writtenBytes = await readFile(backupPath);
		if (!writtenBytes.equals(bytes)) {
			throw new Error(`Native hook transaction backup verification failed for ${backupPath}.`);
		}
	}
	if (options.verbose) {
		console.log(`  backup ${artifact.path} -> ${backupPath}`);
	}
	return true;
}

async function commitNativeHookTransaction(
	artifacts: readonly NativeHookTransactionArtifact[],
	preconditions: readonly NativeHookTransactionPrecondition[],
	ancestorPrecondition: NativeHookTransactionAncestorPrecondition,
	backupContext: SetupBackupContext,
	tracker: RegularFileDurabilityTracker,
	summary: SetupCategorySummary,
	options: Pick<SetupOptions, "dryRun" | "verbose">,
): Promise<void> {
	if (options.dryRun) return;

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Compare sizes and checksums of written vs read-back bytes to confirm corruption
  2. Check disk health and filesystem (avoid network/overlay filesystems for the backup root)
  3. Retry the setup; transient truncation usually does not reproduce
  4. Disable overzealous AV/on-access scanners for the backup directory
Defensive patterns

Strategy: retry

Validate before calling

import { readFile } from "node:fs/promises";
const readBack = await readFile(backupPath);
if (!readBack.equals(expectedBytes)) throw new Error("read-back mismatch before proceeding");

Try / catch

try { await createBackup(artifact); } catch (e) { if (e instanceof Error && e.message.includes("backup verification failed")) { await retryWithBackoff(() => createBackup(artifact), 2); } else throw e; }

Prevention

When it happens

Trigger: readFile(backupPath) returns bytes differing from the written buffer — disk corruption, concurrent writers, encoding transforms, or truncated writes despite fsync.

Common situations: Failing disks, VM/container filesystem quirks, fault-injection in durability tests, or antivirus modifying files on write.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/66e7a5a355be3674. Report an issue: GitHub.