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

Native hook transaction failed and was rolled back: ${messag

Error message

Native hook transaction failed and was rolled back: ${message}

What it means

A native hook transaction hit an error during apply, but rollback completed successfully and restored all artifacts to their pre-transaction state. The original error message is wrapped to make clear that no manual recovery is needed — the system is back to where it started.

Source

Thrown at src/cli/setup.ts:2141

					ancestorPrecondition,
					tracker,
					undefined,
					applied,
				);
				await assertNativeHookTransactionRollbackState(applied);
			} catch (cleanupError) {
				rollbackFailures.push(
					`staged deletion cleanup: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`,
				);
			}
		}
		const message = error instanceof Error ? error.message : String(error);
		if (rollbackFailures.length > 0) {
			throw new Error(
				`Native hook transaction failed (${message}) and rollback failed; manual recovery is required (${rollbackFailures.join("; ")}).`,
			);
		}
		throw new Error(`Native hook transaction failed and was rolled back: ${message}`);
	}
}


async function ensureBackup(
	destinationPath: string,
	contentChanged: boolean,
	backupContext: SetupBackupContext,
	options: Pick<SetupOptions, "dryRun" | "verbose">,
): Promise<boolean> {
	if (!contentChanged || !existsSync(destinationPath)) return false;

	const relativePath = relative(backupContext.baseRoot, destinationPath);
	const safeRelativePath =
		relativePath.startsWith("..") || relativePath === ""
			? destinationPath.replace(/^[/]+/, "")
			: relativePath;
	const backupPath = join(backupContext.backupRoot, safeRelativePath);

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Read the wrapped message to find the original apply failure and fix it
  2. Simply re-run setup after addressing the cause — state was rolled back cleanly
  3. If the cause was concurrent modification, prevent overlapping runs
  4. No manual file recovery is required
Defensive patterns

Strategy: try-catch

Try / catch

try { await tx.apply(); } catch (e) { if (e instanceof Error && e.message.includes("failed and was rolled back")) { /* safe to retry after fixing the wrapped cause */ await fixCauseAndRerun(); } else throw e; }

Prevention

When it happens

Trigger: Any apply-phase failure (invalid hooks output, verification failure, claim failure) where every rollback step succeeds, leaving rollbackFailures empty.

Common situations: Transient write/verification failures, invalid generated hooks content, or single-point fault injection where recovery paths are healthy.

Related errors


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