itsfatduck/optimizerDuck · error · StepExecutionException

Registry verify failed at

Error message

Registry verify failed at {Path}:{Name}: expected '<absent>', actual '{actual}'

What it means

Thrown by VerifyRestore when, after deleting a registry value (NoPreviousValue or RestorePrevious with null Value), the value still reads back as present. The revert write succeeded per the provider, but the value reappears on verification.

Solutions

  1. Re-run the revert elevated so DeleteValue actually succeeds.
  2. Identify and stop the process recreating the value (Process Monitor) before reverting.
  3. Verify you are deleting the same registry view where the value lives (check WOW6432Node).
  4. Delete the value manually in regedit and remove the revert file.

Example fix

// before
if (actual != null)
    throw new StepExecutionException($"...expected '<absent>', actual '{actual}'", null);
// after: one retry of the delete before failing
if (actual != null)
{
    RegistryService.DeleteValue(opCall, new RegistryItem(Path, Name!));
    RegistryService.TryReadValue(new RegistryItem(Path, Name!), out actual, call.Logger);
    if (actual != null) throw new StepExecutionException($"...expected '<absent>', actual '{actual}'", null);
}
Defensive patterns

Strategy: retry

Validate before calling

// ensure no writer holds the key before delete
bool valuePresent = RegistryService.KeyExists(new RegistryItem(step.Path));
logger.LogInformation("Pre-revert key presence at {Path}: {Present}", step.Path, valuePresent);

Type guard

bool IsValueDeletion(RegistryRevertStep s) => s.Action is RevertAction.NoPreviousValue or RevertAction.RestorePrevious && s.Value == null;

Try / catch

for (int attempt = 0; attempt < 2; attempt++)
{
    try { await step.ExecuteAsync(shell, logger); break; }
    catch (StepExecutionException ex) when (ex.Message.Contains("expected '<absent>'") && attempt == 0)
    {
        logger.LogWarning("Value still present; retrying delete once");
    }
}

Prevention

When it happens

Trigger: DeleteValue executed on {Path}:{Name} but TryReadValue returns non-null actual — deletion was denied but reported ok, another process recreated the value between delete and verify, or a different registry view (WOW64) holds a same-named value.

Common situations: Group policy or a background service re-creating the value; ACLs preventing deletion while reads still succeed; the optimization had created the value in a redirected WOW6432Node path while verification reads the 64-bit view.

Related errors


AI-assisted analysis of itsfatduck/optimizerDuck@36acf585ae (2026-09-13). Data as JSON: /api/errors/e0662155374e6f75. Report an issue: GitHub.

Appendix: source

Thrown at optimizerDuck/Domain/Revert/Steps/RegistryRevertStep.cs:286

                break;
            }
            case RevertAction.NoPreviousValue:
            case RevertAction.RestorePrevious:
            {
                // a failed read is not "absent".
                if (
                    !RegistryService.TryReadValue(
                        new RegistryItem(Path, Name!),
                        out var actual,
                        call.Logger
                    )
                )
                    throw new StepExecutionException(
                        $"Registry verify failed at {Path}:{Name}: could not read the value.",
                        null
                    );
                if (actual != null)
                    throw new StepExecutionException(
                        $"Registry verify failed at {Path}:{Name}: expected '<absent>', actual '{actual}'",
                        null
                    );
                break;
            }
            case RevertAction.RestoreKey:
                if (
                    !RegistryService.TryKeyExists(
                        new RegistryItem(Path),
                        out var restoreExists,
                        call.Logger
                    )
                )
                    throw new StepExecutionException(
                        $"Registry verify failed at {Path}: could not query the key.",
                        null
                    );
                if (!restoreExists)

View on GitHub (pinned to 36acf585ae)