itsfatduck/optimizerDuck · error · StepExecutionException

Registry verify failed at

Error message

Registry verify failed at {Path}:{Name}: could not read the value.

What it means

Thrown by RegistryRevertStep.VerifyRestore when a read-back of a restored registry value fails entirely (TryReadValue returns false). After writing the original value back during revert, the step re-reads it to prove the restore took effect; if the value cannot be read at all, the revert is reported as failed.

Solutions

  1. Check that the key Path exists and the value Name is readable in regedit (or via PowerShell Get-ItemProperty).
  2. Verify the revert JSON's Path/Name/Kind fields match the actual registry location, including correct WOW64 view.
  3. Re-run the revert elevated; access-denied reads report as unreadable.
  4. Check logs (call.Logger output) from RegistryService.TryReadValue for the underlying Win32 error.
  5. Restore the value manually and delete the revert file.

Example fix

// before
throw new StepExecutionException($"Registry verify failed at {Path}:{Name}: could not read the value.", null);
// after: pre-check before throwing
if (!RegistryService.KeyExists(new RegistryItem(Path)))
    logger.LogWarning("Key {Path} missing during verify; treating as unrecoverable", Path);
Defensive patterns

Strategy: try-catch

Validate before calling

// before revert
bool keyReadable = RegistryService.KeyExists(new RegistryItem(step.Path));
if (!keyReadable) logger.LogWarning("Key {Path} unreadable before revert", step.Path);

Type guard

bool IsRestorable(RegistryRevertStep s) => s.Action == RevertAction.RestorePrevious && s.Value != null && !string.IsNullOrWhiteSpace(s.Path);

Try / catch

try { await step.ExecuteAsync(shell, logger); }
catch (StepExecutionException ex) when (ex.Message.Contains("could not read the value"))
{
    logger.LogError("Restore lost: value unreadable at revert time. Check key permissions/WOW64 view.");
}

Prevention

When it happens

Trigger: RevertAction.RestorePrevious with a non-null Value, followed by TryReadValue on {Path}:{Name} returning false — key deleted between write and verify, access denied on the key, or the write silently not landing.

Common situations: Security software or another process deleting the key right after the restore; corrupted Path/Name in the revert JSON (e.g. truncated or wrong root prefix); 32/64-bit registry view mismatch redirecting the read to a WOW6432Node key that does not exist.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

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

            Action = Enum.Parse<RevertAction>(data[nameof(Action)]!.ToString()),
            Path = data[nameof(Path)]!.ToString(),
            Name = data[nameof(Name)]?.ToObject<string>(),
            Value = value,
            Kind = kind,
            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,

View on GitHub (pinned to 36acf585ae)