{"record":{"id":"84b25bbc567f56a4","repo":"itsfatduck/optimizerDuck","slug":"registry-verify-failed-at-path-expected-key-to-be-absent-but","errorCode":null,"errorMessage":"Registry verify failed at {Path}: expected key to be absent, but it still exists","messagePattern":"Registry verify failed at (.+?): expected key to be absent, but it still exists","errorType":"exception","errorClass":"StepExecutionException","httpStatus":null,"severity":"error","filePath":"optimizerDuck/Domain/Revert/Steps/RegistryRevertStep.cs","lineNumber":323,"sourceCode":"                    throw new StepExecutionException(\n                        $\"Registry verify failed at {Path}: expected key to exist, but it was missing\",\n                        null\n                    );\n                break;\n            case RevertAction.DeleteKey:\n                if (\n                    !RegistryService.TryKeyExists(\n                        new RegistryItem(Path),\n                        out var deleteExists,\n                        call.Logger\n                    )\n                )\n                    throw new StepExecutionException(\n                        $\"Registry verify failed at {Path}: could not query the key.\",\n                        null\n                    );\n                if (deleteExists)\n                    throw new StepExecutionException(\n                        $\"Registry verify failed at {Path}: expected key to be absent, but it still exists\",\n                        null\n                    );\n                break;\n            default:\n                break;\n        }\n    }\n\n    private static bool ValuesEqual(object? actual, object? expected, RegistryValueKind kind) =>\n        RegistryValues.Equal(actual, expected, kind);\n\n    private async Task<bool> ExecuteSubStepsAsync(ShellService shell, ILogger logger)\n    {\n        if (SubSteps == null)\n            return true;\n        foreach (var step in SubSteps)\n        {","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/itsfatduck/optimizerDuck/blob/36acf585ae122a09f0e29eb4acedfaf94e81c0de/optimizerDuck/Domain/Revert/Steps/RegistryRevertStep.cs#L305-L341","documentation":"Thrown by VerifyRestore during RevertAction.DeleteKey when the key still exists after DeleteSubKeyTree reported success. DeleteSubKeyTree only removes empty key trees; any residual value or subkey (or an open handle) leaves the key in place, so verification fails.","triggerScenarios":"DeleteSubKeyTree(Path) returned Ok but TryKeyExists(Path) finds the key — a subkey/value was recreated after deletion, a process holds an open handle, or the app's DeleteSubKeyTree backup limits (max depth 15 / 5000 items) skipped part of the tree.","commonSituations":"Deep key trees exceeding the revert-step depth/item caps; running services keeping handles on the key; another component recreating the key immediately; non-empty keys when only subkey-less trees can actually be deleted.","solutions":["Check for values/subkeys still under the key in regedit and delete them manually, then retry.","Re-run elevated — access-denied children can silently block tree deletion.","Stop the process holding handles on the key (Process Explorer, 'Find Handle').","If the tree exceeds the backup caps, delete via PowerShell Remove-Item -Recurse and remove the revert file."],"exampleFix":"// before\nif (deleteExists)\n    throw new StepExecutionException($\"Registry verify failed at {Path}: expected key to be absent, but it still exists\", null);\n// after: retry the tree delete once before failing\nif (deleteExists)\n{\n    RegistryService.DeleteSubKeyTree(opCall, new RegistryItem(Path));\n    RegistryService.TryKeyExists(new RegistryItem(Path), out deleteExists, call.Logger);\n    if (deleteExists) throw new StepExecutionException($\"...expected key to be absent, but it still exists\", null);\n}","handlingStrategy":"retry","validationCode":"// pre-check tree contents depth/size expectations\nusing var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(pathAfterRoot);\nint childCount = key?.GetSubKeyNames().Length ?? 0;\nif (childCount > 100) logger.LogWarning(\"Large key tree at {Path}; deletion may exceed backup caps\", path);","typeGuard":"bool IsDeleteKeyStillPresent(StepExecutionException ex) => ex.Message.Contains(\"expected key to be absent, but it still exists\");","tryCatchPattern":"try { await step.ExecuteAsync(shell, logger); }\ncatch (StepExecutionException ex) when (ex.Message.Contains(\"still exists\"))\n{\n    logger.LogWarning(\"Key still present after DeleteSubKeyTree; retrying once elevated\");\n    await step.ExecuteAsync(shell, logger);\n}","preventionTips":["Stop processes holding handles on the key (Process Explorer) before reverting.","Run elevated; denied child keys can block the tree delete.","Avoid optimizations that create very deep/large trees near the 15-depth / 5000-item caps."],"tags":["registry","verify","delete-key","revert"],"backgroundTag":"resource-not-found","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"}