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
- Ensure every Open/Reopen has a matching Close (including in exception paths via try/finally)
- Check UndoManager.OpenedUnit for null before calling Reopen
- 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
- Pair every Open/Reopen with a Close in try/finally
- Close open units on exception paths
- Never nest Reopen calls
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
- SR.TextBoxBase_CantSetIsUndoEnabledInsideChangeBlock
- SR.TextBoxBase_UnmatchedEndChange
- SR.UndoNoOpenUnit
- SR.UndoServiceDisabled
- SR.UndoUnitCantBeOpenedTwice
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)