itsfatduck/optimizerDuck · error · StepExecutionException
Registry verify failed at
Error message
Registry verify failed at {Path}:{Name}: expected '{Value}', actual '{actual}' What it means
Thrown by VerifyRestore when the value read back after a RestorePrevious revert does not equal the originally captured Value for the given RegistryValueKind. The restore 'succeeded' per the write call, but the on-disk registry value differs from the backup.
Solutions
- Compare the Kind field in the revert JSON with the actual value kind shown in regedit and correct it.
- Re-run the revert so it overwrites the intervening change.
- Identify what process rewrote the value (Event Viewer / Process Monitor) and disable it before reverting.
- Set the value manually to the recorded backup Value and remove the revert file.
Example fix
// before
if (!ValuesEqual(actual, Value, Kind))
throw new StepExecutionException($"Registry verify failed at {Path}:{Name}: expected '{Value}', actual '{actual}'", null);
// after: retry the write once before failing
if (!ValuesEqual(actual, Value, Kind))
{
RegistryService.Write(opCall, new RegistryItem(Path, Name!, Value, Kind));
RegistryService.TryReadValue(item, out actual, opCall.Logger);
} Defensive patterns
Strategy: validation
Validate before calling
// before revert, sanity-check backup against current value
using var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(pathAfterRoot);
var current = key?.GetValue(name);
if (current == null) logger.LogWarning("Value missing before restore of {Path}:{Name}", path, name); Type guard
bool KindMatches(RegistryValueKind recorded, object current) => recorded switch
{
RegistryValueKind.DWord => current is int,
RegistryValueKind.QWord => current is long,
RegistryValueKind.String or RegistryValueKind.ExpandString => current is string,
RegistryValueKind.MultiString => current is string[],
RegistryValueKind.Binary => current is byte[],
_ => true
}; Try / catch
try { await step.ExecuteAsync(shell, logger); }
catch (StepExecutionException ex) when (ex.Message.Contains("expected '"))
{
logger.LogError("Value mismatch after restore; a concurrent writer likely changed {Path}", step.Path);
} Prevention
- Ensure optimizations stop services/processes that rewrite the same values before applying.
- Record the correct RegistryValueKind at backup time.
- Re-check applied state shortly after revert; retry if a background writer interfered.
When it happens
Trigger: RevertAction.RestorePrevious with Value != null and RegistryValues.Equal(actual, Value, Kind) returning false — e.g. DWORD 0x1 vs '1' string kind mismatch, ExpandString vs String round-trip differences, or a concurrent process overwriting the value between write and read-back.
Common situations: Kind recorded in the revert JSON differs from the value's actual registry kind (e.g. optimization wrote REG_SZ but backup says REG_DWORD); environment-variable expansion changing ExpandString content; race with a service resetting the same value.
Related errors
- Registry verify failed at
- Registry verify failed at
- Registry verify failed at
- Registry verify failed at
- Registry verify failed at
AI-assisted analysis of itsfatduck/optimizerDuck@36acf585ae (2026-09-13).
Data as JSON: /api/errors/b5b569a1c08c5bf4.
Report an issue: GitHub.
Appendix: source
Thrown at optimizerDuck/Domain/Revert/Steps/RegistryRevertStep.cs:264
CreatedSubKeys = createdSubKeys,
SubSteps = subSteps,
};
}
private void VerifyRestore(OpCall call)
{
switch (Action)
{
case RevertAction.RestorePrevious when Value != null:
{
var item = new RegistryItem(Path, Name!);
if (!RegistryService.TryReadValue(item, out var actual, call.Logger))
throw new StepExecutionException(
$"Registry verify failed at {Path}:{Name}: could not read the value.",
null
);
if (!ValuesEqual(actual, Value, Kind))
throw new StepExecutionException(
$"Registry verify failed at {Path}:{Name}: expected '{Value}', actual '{actual}'",
null
);
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.",View on GitHub (pinned to 36acf585ae)