{"record":{"id":"a5b8b4b98f599900","repo":"dotnet/wpf","slug":"cannot-reopen-a-popup-in-the-closed-event-handler","errorCode":null,"errorMessage":"Cannot reopen a popup in the closed event handler.","messagePattern":"Cannot reopen a popup in the closed event handler\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Primitives/Popup.cs","lineNumber":351,"sourceCode":"        /// <summary>\n        ///     Called when IsOpenProperty is changed on \"d.\"\n        /// </summary>\n        private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\n        {\n            Popup popup = (Popup)d;\n\n            // This is actually the current state and not necessary the desired state (i.e. old value)\n            bool currentVisible = (popup._secHelper.IsWindowAlive() && (popup._asyncDestroy == null)) || (popup._asyncCreate != null);\n            bool visible = (bool) e.NewValue;\n\n            if (visible != currentVisible)\n            {\n                if (visible)\n                {\n                    // The popup wants to be visible\n\n                    if (popup._cacheValid[(int)CacheBits.OnClosedHandlerReopen])\n                        throw new InvalidOperationException(SR.PopupReopeningNotAllowed);\n\n                    popup.CancelAsyncDestroy();\n\n                    // Cancel any pending async create requests, we're creating now\n                    popup.CancelAsyncCreate();\n                    popup.CreateWindow(false /*asyncCall*/);\n\n                    // It is possible that the popup is destroyed by CreateWindow or one of its callbacks\n                    if (popup._secHelper.IsWindowAlive())\n                    {\n                        // Close the popup when it is unloaded from the visual tree\n                        if (CloseOnUnloadedHandler == null)\n                        {\n                            CloseOnUnloadedHandler = new RoutedEventHandler(CloseOnUnloaded);\n                        }\n\n                        popup.Unloaded += CloseOnUnloadedHandler;\n                    }","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Primitives/Popup.cs#L333-L369","documentation":"WPF's Popup throws this InvalidOperationException when code calls IsOpen=true (or Show) from inside the popup's Closed event handler. The popup caches a flag (CacheBits.OnClosedHandlerReopen) set while the Closed handler runs, and re-opening during close processing would corrupt the window lifecycle. You must wait until close processing finishes before re-showing.","triggerScenarios":"Setting popup.IsOpen = true (or calling SetCurrentValue(IsOpenProperty, true)) synchronously inside the Closed event handler or OnClosed override, e.g. to immediately relocate/re-show the popup.","commonSituations":"Developers chaining popups ('close this one, then open another'), implementing flyout animations that re-show the popup after a fade, or auto-reopen logic after a dismiss.","solutions":["Defer the reopen by posting it to the dispatcher: Dispatcher.BeginInvoke(() => popup.IsOpen = true, DispatcherPriority.Input) instead of setting IsOpen inside Closed.","Restructure logic so the popup stays open (move/resize it) rather than closing and reopening.","If the reopen is intentional and valid, ensure the Closed handler returned before setting IsOpen (e.g. via async continuation)."],"exampleFix":"// before\npopup.Closed += (s, e) => popup.IsOpen = true; // throws\n// after\npopup.Closed += (s, e) =>\n    Dispatcher.BeginInvoke(new Action(() => popup.IsOpen = true), DispatcherPriority.Input);","handlingStrategy":"try-catch","validationCode":"// Cannot reliably pre-check; instead check the flag indirectly:\nbool closing = popup.IsOpen == false; // only reopen after handler returns\nif (!closing) popup.IsOpen = true;","typeGuard":null,"tryCatchPattern":"try { popup.IsOpen = true; }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"reopen\")) {\n    Dispatcher.BeginInvoke(new Action(() => popup.IsOpen = true), DispatcherPriority.Input);\n}","preventionTips":["Never mutate IsOpen synchronously inside Closed handlers","Use Dispatcher.BeginInvoke for deferred reopen","Prefer repositioning an open popup over close/reopen cycles"],"tags":["wpf","popup","invalid-state-transition"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}