dotnet/wpf · error · InvalidOperationException
SR.UndoNoOpenUnit
Error message
SR.UndoNoOpenUnit
What it means
InvalidOperationException from UndoManager.Close: there is no currently open parent undo unit to close — Close was called without a matching prior Open (or the unit was already closed), so the close operation has no target.
Solutions
- Check UndoManager.OpenedUnit != null before calling Close
- Ensure each Open has exactly one Close (use try/finally with a closed flag)
- Skip Close when Open was never reached or failed
Example fix
// before
undoManager.Open(unit);
...
undoManager.Close(unit, UndoCloseAction.Commit);
undoManager.Close(unit, UndoCloseAction.Commit); // throws
// after
undoManager.Open(unit);
...
if (undoManager.OpenedUnit != null)
{
undoManager.Close(unit, UndoCloseAction.Commit);
} Defensive patterns
Strategy: validation
Validate before calling
if (undoManager.OpenedUnit == null) { /* nothing open: skip Close */ } Try / catch
try { undoManager.Close(unit, UndoCloseAction.Commit); } catch (InvalidOperationException ex) when (ex.Message.Contains("no open unit")) { /* nothing to close: ignore */ } Prevention
- Track open/close pairing with a flag
- Close exactly once per Open
- Skip Close when Open was skipped or failed
When it happens
Trigger: Calling Close without a matching Open, calling Close twice for the same unit, or Close after an exception path already closed the unit.
Common situations: Double-close from both a text-change handler and a finally block, or Close in cleanup code when Open was skipped because undo was disabled.
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.UndoServiceDisabled
- SR.UndoUnitAlreadyOpen
- SR.UndoUnitCantBeOpenedTwice
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/2678dc56be2d0c31.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/UndoManager.cs:322
/// Thrown if:
/// UndoManager is disabled
/// no undo unit is currently open
/// </exception>
/// <exception cref="ArgumentNullException">
/// Thrown if unit is null
/// </exception>
internal void Close(IParentUndoUnit unit, UndoCloseAction closeAction)
{
if (!IsEnabled)
{
throw new InvalidOperationException(SR.UndoServiceDisabled);
}
ArgumentNullException.ThrowIfNull(unit);
if (OpenedUnit == null)
{
throw new InvalidOperationException(SR.UndoNoOpenUnit);
}
// find the parent of the given unit
if (OpenedUnit != unit)
{
IParentUndoUnit closeParent;
closeParent = OpenedUnit;
while (closeParent.OpenedUnit != null && closeParent.OpenedUnit != unit)
{
closeParent = closeParent.OpenedUnit;
}
if (closeParent.OpenedUnit == null)
{
throw new ArgumentException(SR.UndoUnitNotFound, nameof(unit));
}View on GitHub (pinned to 81131a70a4)