{"record":{"id":"b5b569a1c08c5bf4","repo":"itsfatduck/optimizerDuck","slug":"registry-verify-failed-at-path-name-expected-value-actual","errorCode":null,"errorMessage":"Registry verify failed at {Path}:{Name}: expected '{Value}', actual '{actual}'","messagePattern":"Registry verify failed at (.+?):(.+?): expected '(.+?)', actual '(.+?)'","errorType":"exception","errorClass":"StepExecutionException","httpStatus":null,"severity":"error","filePath":"optimizerDuck/Domain/Revert/Steps/RegistryRevertStep.cs","lineNumber":264,"sourceCode":"            CreatedSubKeys = createdSubKeys,\n            SubSteps = subSteps,\n        };\n    }\n\n    private void VerifyRestore(OpCall call)\n    {\n        switch (Action)\n        {\n            case RevertAction.RestorePrevious when Value != null:\n            {\n                var item = new RegistryItem(Path, Name!);\n                if (!RegistryService.TryReadValue(item, out var actual, call.Logger))\n                    throw new StepExecutionException(\n                        $\"Registry verify failed at {Path}:{Name}: could not read the value.\",\n                        null\n                    );\n                if (!ValuesEqual(actual, Value, Kind))\n                    throw new StepExecutionException(\n                        $\"Registry verify failed at {Path}:{Name}: expected '{Value}', actual '{actual}'\",\n                        null\n                    );\n                break;\n            }\n            case RevertAction.NoPreviousValue:\n            case RevertAction.RestorePrevious:\n            {\n                // a failed read is not \"absent\".\n                if (\n                    !RegistryService.TryReadValue(\n                        new RegistryItem(Path, Name!),\n                        out var actual,\n                        call.Logger\n                    )\n                )\n                    throw new StepExecutionException(\n                        $\"Registry verify failed at {Path}:{Name}: could not read the value.\",","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/itsfatduck/optimizerDuck/blob/36acf585ae122a09f0e29eb4acedfaf94e81c0de/optimizerDuck/Domain/Revert/Steps/RegistryRevertStep.cs#L246-L282","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nif (!ValuesEqual(actual, Value, Kind))\n    throw new StepExecutionException($\"Registry verify failed at {Path}:{Name}: expected '{Value}', actual '{actual}'\", null);\n// after: retry the write once before failing\nif (!ValuesEqual(actual, Value, Kind))\n{\n    RegistryService.Write(opCall, new RegistryItem(Path, Name!, Value, Kind));\n    RegistryService.TryReadValue(item, out actual, opCall.Logger);\n}","handlingStrategy":"validation","validationCode":"// before revert, sanity-check backup against current value\nusing var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(pathAfterRoot);\nvar current = key?.GetValue(name);\nif (current == null) logger.LogWarning(\"Value missing before restore of {Path}:{Name}\", path, name);","typeGuard":"bool KindMatches(RegistryValueKind recorded, object current) => recorded switch\n{\n    RegistryValueKind.DWord => current is int,\n    RegistryValueKind.QWord => current is long,\n    RegistryValueKind.String or RegistryValueKind.ExpandString => current is string,\n    RegistryValueKind.MultiString => current is string[],\n    RegistryValueKind.Binary => current is byte[],\n    _ => true\n};","tryCatchPattern":"try { await step.ExecuteAsync(shell, logger); }\ncatch (StepExecutionException ex) when (ex.Message.Contains(\"expected '\"))\n{\n    logger.LogError(\"Value mismatch after restore; a concurrent writer likely changed {Path}\", step.Path);\n}","preventionTips":["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."],"tags":["registry","verify","revert","value-mismatch"],"backgroundTag":"unexpected-response-shape","analyzedSha":"36acf585ae122a09f0e29eb4acedfaf94e81c0de","analyzedAt":"2026-09-13T08:30:13.845Z","contentChangedAt":"2026-09-13T08:30:13.845Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}