dotnet/wpf · error
Cannot reopen a popup in the closed event handler.
Error message
Cannot reopen a popup in the closed event handler.
What it means
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.
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).
Example fix
// before
popup.Closed += (s, e) => popup.IsOpen = true; // throws
// after
popup.Closed += (s, e) =>
Dispatcher.BeginInvoke(new Action(() => popup.IsOpen = true), DispatcherPriority.Input); Defensive patterns
Strategy: try-catch
Validate before calling
// Cannot reliably pre-check; instead check the flag indirectly: bool closing = popup.IsOpen == false; // only reopen after handler returns if (!closing) popup.IsOpen = true;
Try / catch
try { popup.IsOpen = true; }
catch (InvalidOperationException ex) when (ex.Message.Contains("reopen")) {
Dispatcher.BeginInvoke(new Action(() => popup.IsOpen = true), DispatcherPriority.Input);
} Prevention
- Never mutate IsOpen synchronously inside Closed handlers
- Use Dispatcher.BeginInvoke for deferred reopen
- Prefer repositioning an open popup over close/reopen cycles
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- ' ' must be the root element of a tree, but has a logical…
- Microsoft.Windows.Controls.SR.ResizeParametersNotValid
- SR.AnnotationServiceNotEnabled
- SR.CannotBeInsidePopup
- SR.CollectionViewTypeIsInitOnly
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/a5b8b4b98f599900.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Primitives/Popup.cs:351
/// <summary>
/// Called when IsOpenProperty is changed on "d."
/// </summary>
private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Popup popup = (Popup)d;
// This is actually the current state and not necessary the desired state (i.e. old value)
bool currentVisible = (popup._secHelper.IsWindowAlive() && (popup._asyncDestroy == null)) || (popup._asyncCreate != null);
bool visible = (bool) e.NewValue;
if (visible != currentVisible)
{
if (visible)
{
// The popup wants to be visible
if (popup._cacheValid[(int)CacheBits.OnClosedHandlerReopen])
throw new InvalidOperationException(SR.PopupReopeningNotAllowed);
popup.CancelAsyncDestroy();
// Cancel any pending async create requests, we're creating now
popup.CancelAsyncCreate();
popup.CreateWindow(false /*asyncCall*/);
// It is possible that the popup is destroyed by CreateWindow or one of its callbacks
if (popup._secHelper.IsWindowAlive())
{
// Close the popup when it is unloaded from the visual tree
if (CloseOnUnloadedHandler == null)
{
CloseOnUnloadedHandler = new RoutedEventHandler(CloseOnUnloaded);
}
popup.Unloaded += CloseOnUnloadedHandler;
}View on GitHub (pinned to 81131a70a4)