can1357/oh-my-pi · error · Error

${formatVerificationFailure(verification, options.expectedVe

Error message

${formatVerificationFailure(verification, options.expectedVersion)}; restored previous ${APP_NAME} binary

What it means

Thrown during the binary swap step of `omp update` when, after renaming the new binary into place, the post-install verification (`verifyInstalledVersion`) reports the installed version does not match the expected version. The previous binary was restored from backup, and the message combines the verification-failure detail with that recovery note.

Source

Thrown at packages/coding-agent/src/cli/update-cli.ts:1295

		// `backupPath` is unique per attempt (see updateViaBinaryAt), so this rename
		// never has to overwrite — or unlink — a possibly-locked leftover from an
		// earlier run. Renaming the running executable itself is permitted on
		// Windows; only deleting its still-mapped image is not.
		// A missing target is tolerated: repairing a launcher that a failed
		// package-manager reinstall removed installs the binary at a vacant
		// path. There is then nothing to restore, so a verification failure
		// leaves the new binary in place rather than the previous nothing.
		try {
			await fs.promises.rename(options.targetPath, options.backupPath);
			backupReady = true;
		} catch (err) {
			if (!isEnoent(err)) throw err;
		}
		await fs.promises.rename(options.tempPath, options.targetPath);

		const verification = await options.verifyInstalledVersion(options.expectedVersion);
		if (!verification.ok) {
			throw new Error(
				`${formatVerificationFailure(verification, options.expectedVersion)}; restored previous ${APP_NAME} binary`,
			);
		}

		backupReady = false;
		// Swap done and verified. On Windows the backup is still the running
		// process image and cannot be unlinked until this process exits, so a
		// failure here must NOT fail an otherwise-successful update.
		await removeBackupBestEffort(options.backupPath);
		return verification;
	} catch (err) {
		if (backupReady) {
			await unlinkIfExists(options.targetPath);
			await fs.promises.rename(options.backupPath, options.targetPath);
		}
		await unlinkIfExists(options.tempPath);
		throw err;
	}

View on GitHub (pinned to 9690622007)

Solutions

  1. Retry `omp update` — the previous binary was restored, so nothing is broken
  2. Check AV/EDR quarantine logs and allowlist the omp binary path
  3. Verify the released asset's version matches expectations (regression on the release side) and report it
  4. Update manually: download the binary from GitHub releases and replace the install yourself

Example fix

// before: AV keeps quarantining the new binary
omp update  // verification failed; restored previous binary
// after: allowlist the install dir, then retry
# e.g. Windows Defender exclusion for the omp install path
omp update
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await runUpdate();
} catch (err) {
  if (String(err?.message).includes("restored previous")) {
    // the old binary is intact; safe to retry or report
    console.error(`Update rolled back: ${err.message}`);
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: `options.verifyInstalledVersion(options.expectedVersion)` returns {ok:false} right after `fs.promises.rename(tempPath, targetPath)` — e.g. the new binary immediately crashes, reports a different version, AV quarantined the file, or the rename landed a corrupt download.

Common situations: Antivirus/EDR blocking or quarantining the freshly written executable, partial/corrupted download that still ran, filesystem sync issues on network drives, or a build uploaded with a mismatched version string.

Related errors


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