dotnet/wpf · error · InvalidOperationException

SR.UndoUnitAlreadyOpen

Error message

SR.UndoUnitAlreadyOpen

What it means

InvalidOperationException from UndoManager.Reopen: another parent undo unit is already open on this undo stack, and only one open unit is allowed at a time (nested units must be closed or reopened via the open unit itself).

Solutions

  1. Ensure every Open/Reopen has a matching Close (including in exception paths via try/finally)
  2. Check UndoManager.OpenedUnit for null before calling Reopen
  3. Close the current unit with an appropriate UndoCloseAction before reopening

Example fix

// before
undoManager.Reopen(unit);
// after
if (undoManager.OpenedUnit == null)
{
    undoManager.Reopen(unit);
}
Defensive patterns

Strategy: validation

Validate before calling

if (undoManager.OpenedUnit != null) { /* close current unit first */ }

Try / catch

try { undoManager.Reopen(unit); } catch (InvalidOperationException ex) when (ex.Message.Contains("already open")) { /* close the open unit then retry */ }

Prevention

When it happens

Trigger: Calling Reopen while OpenedUnit is non-null, e.g. nested OpenCompositionUndoUnit/OpenTypingUndoUnit calls without closing the previous unit first.

Common situations: Overlapping IME composition events, or a typing undo unit opened on top of a still-open composition unit because Close was skipped on an exception path.

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/113f1f8e118fd483. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/UndoManager.cs:246

        ///     another unit is already open
        ///     the given unit is locked
        ///     the given unit is not on top of the stack
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// Thrown if passed unit is null.
        /// </exception>
        internal void Reopen(IParentUndoUnit unit)
        {
            if (!IsEnabled)
            {
                throw new InvalidOperationException(SR.UndoServiceDisabled);
            }

            ArgumentNullException.ThrowIfNull(unit);

            if (OpenedUnit != null)
            {
                throw new InvalidOperationException(SR.UndoUnitAlreadyOpen);
            }

            switch (State)
            {
                case UndoState.Normal:
                case UndoState.Redo:
                    {
                        if (UndoCount == 0 || PeekUndoStack() != unit)
                        {
                            throw new InvalidOperationException(SR.UndoUnitNotOnTopOfStack);
                        }

                        break;
                    }

                case UndoState.Undo:
                    {
                        if (RedoStack.Count == 0 || (IParentUndoUnit)RedoStack.Peek() != unit)

View on GitHub (pinned to 81131a70a4)