dotnet/wpf · error · ArgumentException

SR.UndoUnitNotFound

Error message

SR.UndoUnitNotFound

What it means

When closing a nested undo unit, Close walks down the chain of OpenedUnits looking for the unit's parent. If the traversal finds a parent whose OpenedUnit is null, the requested `unit` is not open anywhere in this hierarchy, so ArgumentException(SR.UndoUnitNotFound, nameof(unit)) is thrown.

Solutions

  1. Verify the unit instance is the one previously passed to Open on this parent chain (reference equality, not value).
  2. Re-check the open/close order: close deepest-first, innermost unit first.
  3. Discard references to units after a Clear/Reset of the undo manager instead of closing them.
  4. Wrap in try/catch for recovery if unit lifecycle cannot be tracked strictly.

Example fix

// before
if (parentUnit != null) parentUnit.Close(unit, action); // unit may be from another manager
// after
if (parentUnit != null && IsOpenInHierarchy(parentUnit, unit))
{
    parentUnit.Close(unit, action);
}
Defensive patterns

Strategy: validation

Validate before calling

bool unitBelongsToHierarchy = ReferenceEquals(parentUnit.OpenedUnit, unit)
    || ContainsUnit(parentUnit, unit); // walk your own open-unit bookkeeping

Type guard

bool IsTrackedUnit(IUndoUnit u) => openedUnits.Contains(u);

Try / catch

try { parentUnit.Close(unit, action); }
catch (ArgumentException ex) when (ex.ParamName == "unit")
{
    // unit not open in this hierarchy: discard reference
}

Prevention

When it happens

Trigger: Calling Close(unit, action) passing a unit that was never opened, already closed, or belongs to a different ParentUndoUnit/UndoManager hierarchy.

Common situations: Holding stale unit references after the undo stack was cleared; closing a sibling unit instead of the open child; mixing units across multiple TextBox/undo-manager instances.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/ParentUndoUnit.cs:130

            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));
                }

                if (closeParent != this)
                {
                    closeParent.Close(closeAction);
                    return;
                }
            }

            //
            // Close our open unit
            //

            // Get the undo manager
            undoManager = TopContainer as UndoManager;

            if (closeAction != UndoCloseAction.Commit)
            {

View on GitHub (pinned to 81131a70a4)