dotnet/wpf · error · InvalidOperationException

SR.ShowDialogOnModal

Error message

SR.ShowDialogOnModal

What it means

Only one modal dialog session can run on a Window at a time. If ShowDialog is invoked while the window is already showing as a dialog (_showingAsDialog is true), WPF throws InvalidOperationException(SR.ShowDialogOnModal). This prevents nested/re-entrant modal loops on the same window instance.

Solutions

  1. Never call ShowDialog on the same window instance while it is modal; show a different (child) window instead
  2. Guard with a _showingAsDialog-equivalent flag or check window.IsVisible before calling
  3. Create a fresh Window instance for each modal invocation
  4. Route repeated requests to the existing dialog and bring it to the foreground instead

Example fix

// before
private void Reopen(object s, RoutedEventArgs e) {
    this.ShowDialog(); // re-entrant on same window -> throws
}
// after
private void Reopen(object s, RoutedEventArgs e) {
    if (!_showingAsDialog && !IsVisible) {
        ShowDialog();
    } else {
        Activate(); // bring existing dialog forward
    }
}
Defensive patterns

Strategy: validation

Validate before calling

if (!window.IsVisible && !ReferenceEqualityComparer.Instance.Equals(window, activeWindowShowingDialog)) { window.ShowDialog(); }

Type guard

bool CanShowModal(Window w) => !w.IsVisible;

Try / catch

try { window.ShowDialog(); } catch (InvalidOperationException ex) when (ex.Message == SR.ShowDialogOnModal) { window.Activate(); /* already modal */ }

Prevention

When it happens

Trigger: Calling ShowDialog() again from within the dialog's own event handlers, from code re-entered during the modal message loop, or from multiple threads/commands targeting the same window instance concurrently.

Common situations: A dialog's button handler calling ShowDialog on itself; a command executing ShowDialog re-entrantly while a modal session is active; a shared singleton dialog window opened from two places.

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


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/b92e37b93d6f9bc8. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Window.cs:284

        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        /// </remarks>
        public Nullable<bool> ShowDialog()
        {
            // this call ends up throwing an exception if ShowDialog
            // is not allowed
            VerifyApiSupported();
            VerifyContextAndObjectState();
            VerifyCanShow();
            VerifyNotClosing();
            VerifyConsistencyWithAllowsTransparency();

            if (_isVisible)
            {
                throw new InvalidOperationException(SR.ShowDialogOnVisible);
            }
            else if (_showingAsDialog)
            {
                throw new InvalidOperationException(SR.ShowDialogOnModal);
            }

            _dialogOwnerHandle = _ownerHandle;

            // verify owner handle is window
            if (!UnsafeNativeMethods.IsWindow( new HandleRef( null, _dialogOwnerHandle ) ))
            {
                _dialogOwnerHandle = IntPtr.Zero;
            }


            // remember the current active window;
            // this is used when dialog creation fails or dialog closes, we set the active window back to this one.
            _dialogPreviousActiveHandle = UnsafeNativeMethods.GetActiveWindow();

            // if owner window is not specified, we get the current active window on this thread's
            // message queue as the owner.
            if (_dialogOwnerHandle == IntPtr.Zero)

View on GitHub (pinned to 81131a70a4)