{"record":{"id":"2098c7af87655d80","repo":"BCUninstaller/Bulk-Crap-Uninstaller","slug":"hotkey-handler-called-when-parent-form-was-null","errorCode":null,"errorMessage":"Hotkey handler called when parent form was null","messagePattern":"Hotkey handler called when parent form was null","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"source/KlocTools/Subsystems/GlobalHotkeys.cs","lineNumber":132,"sourceCode":"                ParentForm = ContainerControl.ParentForm;\n            else\n                throw new InvalidOperationException(\"Could not find the parent form\");\n        }\n\n        protected override void Dispose(bool disposing)\n        {\n            if (disposing)\n            {\n                ParentForm = null;\n                Clear();\n            }\n            base.Dispose(disposing);\n        }\n\n        private void KeyDown_Handler(object sender, KeyEventArgs e)\n        {\n            if (_parentForm == null)\n                throw new InvalidOperationException(\"Hotkey handler called when parent form was null\");\n\n            foreach (var hotkey in _registeredHotkeys)\n            {\n                if (hotkey.Alt == e.Alt && hotkey.Ctrl == e.Control && hotkey.Shift == e.Shift &&\n                    hotkey.KeyCode == e.KeyCode)\n                {\n                    if (hotkey.EventHandler == null || !hotkey.IsEnabled ||\n                        (StopWhenFormIsDisabled && !ParentForm.Enabled))\n                        continue;\n\n                    hotkey.EventHandler(_parentForm, EventArgs.Empty);\n\n                    // Stops default windows \"wtfding\" sound and prevents event bubbling\n                    if (SuppressKeyPresses)\n                        e.SuppressKeyPress = true;\n\n                    // Do not process any more hotkeys\n                    return;","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/BCUninstaller/Bulk-Crap-Uninstaller/blob/608321de98e92297377b1eb69029af55c25504a1/source/KlocTools/Subsystems/GlobalHotkeys.cs#L114-L150","documentation":"Thrown inside GlobalHotkeys.KeyDown_Handler, the KeyPreview event handler attached to the parent form. If _parentForm is null when a key event arrives it raises InvalidOperationException. Because ParentForm is set to null during Dispose(true), this can fire if a queued key event is delivered after disposal or if the handler was subscribed but ParentForm was never assigned.","triggerScenarios":"A KeyDown event raised on a form whose GlobalHotkeys._parentForm is null — typically a keystroke delivered during/after Dispose (race with ParentForm=null), or manual subscription without ever setting ParentForm.","commonSituations":"Form closing while a key is still in the input queue, re-parenting logic that nulls ParentForm then re-raises focus, or unit-test harnesses that synthesise KeyEvents without a form.","solutions":["Dispose the GlobalHotkeys component before the form closes so the handler detaches (the setter removes the KeyDown subscription).","Guard consumers by ensuring ParentForm is non-null for the lifetime of the subscription.","If you control a fork, downgrade the throw to an early return when _parentForm == null."],"exampleFix":"// before: form closes, queued KeyDown fires after ParentForm set to null -> throws\n\n// after: dispose the component first so the handler unsubscribes\nprotected override void OnFormClosing(FormClosingEventArgs e)\n{\n    globalHotkeys1.Dispose();\n    base.OnFormClosing(e);\n}","handlingStrategy":"try-catch","validationCode":"if (globalHotkeys1.ParentForm == null) return; // no form, skip synthesised events","typeGuard":null,"tryCatchPattern":"try { /* code raising KeyDown synthetically */ }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"parent form was null\"))\n{ /* component disposed mid-event; ignore */ }","preventionTips":["Dispose GlobalHotkeys before the form closes so the handler unsubscribes.","Never null ParentForm while the form can still receive keystrokes.","In test harnesses, set ParentForm before pumping KeyEvents."],"tags":["winforms","race-condition","disposal","csharp","kloctools"],"backgroundTag":null,"analyzedSha":"608321de98e92297377b1eb69029af55c25504a1","analyzedAt":"2026-08-13T12:17:35.389Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}