{"record":{"id":"66e7a5a355be3674","repo":"Yeachan-Heo/oh-my-codex","slug":"native-hook-transaction-backup-verification-failed","errorCode":null,"errorMessage":"Native hook transaction backup verification failed for ${backupPath}.","messagePattern":"Native hook transaction backup verification failed for (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/setup.ts","lineNumber":2006,"sourceCode":"\t\t\t\tif (createdStat.isSymbolicLink() || !createdStat.isDirectory()) {\n\t\t\t\t\tthrow new Error(`Refusing to use unsafe created backup ancestor ${currentPath}.`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst handle = await open(backupPath, \"wx\", 0o600);\n\t\ttry {\n\t\t\tawait handle.writeFile(bytes);\n\t\t\trecordRegularFileSyncOutcome(tracker, await syncNativeHookRegularFile(handle));\n\t\t} finally {\n\t\t\tawait handle.close();\n\t\t}\n\t\tconst backupStat = await lstat(backupPath);\n\t\tif (backupStat.isSymbolicLink() || !backupStat.isFile() || backupStat.nlink !== 1) {\n\t\t\tthrow new Error(`Refusing unsafe native hook transaction backup ${backupPath}.`);\n\t\t}\n\t\tconst writtenBytes = await readFile(backupPath);\n\t\tif (!writtenBytes.equals(bytes)) {\n\t\t\tthrow new Error(`Native hook transaction backup verification failed for ${backupPath}.`);\n\t\t}\n\t}\n\tif (options.verbose) {\n\t\tconsole.log(`  backup ${artifact.path} -> ${backupPath}`);\n\t}\n\treturn true;\n}\n\nasync function commitNativeHookTransaction(\n\tartifacts: readonly NativeHookTransactionArtifact[],\n\tpreconditions: readonly NativeHookTransactionPrecondition[],\n\tancestorPrecondition: NativeHookTransactionAncestorPrecondition,\n\tbackupContext: SetupBackupContext,\n\ttracker: RegularFileDurabilityTracker,\n\tsummary: SetupCategorySummary,\n\toptions: Pick<SetupOptions, \"dryRun\" | \"verbose\">,\n): Promise<void> {\n\tif (options.dryRun) return;","sourceCodeStart":1988,"sourceCodeEnd":2024,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/setup.ts#L1988-L2024","documentation":"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.","triggerScenarios":"readFile(backupPath) returns bytes differing from the written buffer — disk corruption, concurrent writers, encoding transforms, or truncated writes despite fsync.","commonSituations":"Failing disks, VM/container filesystem quirks, fault-injection in durability tests, or antivirus modifying files on write.","solutions":["Compare sizes and checksums of written vs read-back bytes to confirm corruption","Check disk health and filesystem (avoid network/overlay filesystems for the backup root)","Retry the setup; transient truncation usually does not reproduce","Disable overzealous AV/on-access scanners for the backup directory"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import { readFile } from \"node:fs/promises\";\nconst readBack = await readFile(backupPath);\nif (!readBack.equals(expectedBytes)) throw new Error(\"read-back mismatch before proceeding\");","typeGuard":null,"tryCatchPattern":"try { await createBackup(artifact); } catch (e) { if (e instanceof Error && e.message.includes(\"backup verification failed\")) { await retryWithBackoff(() => createBackup(artifact), 2); } else throw e; }","preventionTips":["Use reliable local disks for the backup root","Exclude backup dirs from antivirus on-access scanning","Checksum backups after creation in critical flows"],"tags":["backup","verification","disk-corruption","file-integrity"],"backgroundTag":"write-verification-failed","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}