dotnet/wpf · error · InvalidOperationException
SR.UndoNoOpenUnit
Error message
SR.UndoNoOpenUnit
What it means
ParentUndoUnit.Close(unit, closeAction) closes the currently open child undo unit. If this parent has no OpenedUnit, there is nothing to close, so InvalidOperationException(SR.UndoNoOpenUnit) is thrown to report the unbalanced Open/Close state.
Solutions
- Check OpenedUnit != null (or that it equals the unit you intend to close) before calling Close.
- Use try/finally so Open/Close remain balanced even when edits throw.
- Ensure the unit you pass to Close is the exact unit returned/held from the Open call.
- If the manager was reset (UndoManager.Clear/Reset), discard pending unit references instead of closing them.
Example fix
// before
parentUndoUnit.Close(unit, undoCloseAction);
// after
if (parentUndoUnit.OpenedUnit == unit)
{
parentUndoUnit.Close(unit, undoCloseAction);
} Defensive patterns
Strategy: validation
Validate before calling
if (unit == null) throw new ArgumentNullException(nameof(unit)); bool closable = parentUnit.OpenedUnit != null;
Type guard
bool HasOpenUnit(ParentUndoUnit p) => p?.OpenedUnit != null;
Try / catch
try { parentUnit.Close(unit, action); }
catch (InvalidOperationException ex) when (ex.Message.Contains("no open unit"))
{
// unbalanced close: drop the stale reference
} Prevention
- Track open/close pairing explicitly in transaction objects
- Never close a unit twice
- Invalidate held unit references after UndoManager.Clear/Reset
When it happens
Trigger: Calling Close on a ParentUndoUnit (or a unit reached through the parent chain) when OpenedUnit is null — i.e. Close called without a matching Open, or Close called twice for the same unit.
Common situations: Double-close in exception handling paths; closing an undo unit after the undo stack was reset/cleared; mismatched Open/Close pairing across re-entrant text edit events.
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.UndoUnitCantBeAddedTwice
- SR.UndoUnitCantBeOpenedTwice
- Current DocumentSequence, FixedDocument, or FixedPage not…
- IAmbientProvider
- InvalidOperationException()
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/8b7575a3e4c593f7.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/ParentUndoUnit.cs:114
/// IParentUndoUnit to close. If NULL, this unit's OpenedUnit is closed.
/// </param>
/// <param name="closeAction">
/// </param>
/// <exception cref="InvalidOperationException">
/// Thrown if no undo unit is currently open
/// </exception>
/// <exception cref="ArgumentNullException">
/// Thrown if unit is null
/// </exception>
public virtual void Close(IParentUndoUnit unit, UndoCloseAction closeAction)
{
UndoManager undoManager;
ArgumentNullException.ThrowIfNull(unit);
if (OpenedUnit == null)
{
throw new InvalidOperationException(SR.UndoNoOpenUnit);
}
// find the parent of the given unit
if (OpenedUnit != unit)
{
IParentUndoUnit closeParent;
closeParent = this;
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)