{"record":{"id":"c1975f7564346138","repo":"dotnet/wpf","slug":"sr-undounitnotfound","errorCode":null,"errorMessage":"SR.UndoUnitNotFound","messagePattern":"SR\\.UndoUnitNotFound","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/ParentUndoUnit.cs","lineNumber":130,"sourceCode":"            if (OpenedUnit == null)\n            {\n                throw new InvalidOperationException(SR.UndoNoOpenUnit);\n            }\n\n            // find the parent of the given unit\n            if (OpenedUnit != unit)\n            {\n                IParentUndoUnit closeParent;\n\n                closeParent = this;\n                while (closeParent.OpenedUnit != null && closeParent.OpenedUnit != unit)\n                {\n                    closeParent = closeParent.OpenedUnit;\n                }\n\n                if (closeParent.OpenedUnit == null)\n                {\n                    throw new ArgumentException(SR.UndoUnitNotFound, nameof(unit));\n                }\n\n                if (closeParent != this)\n                {\n                    closeParent.Close(closeAction);\n                    return;\n                }\n            }\n\n            //\n            // Close our open unit\n            //\n\n            // Get the undo manager\n            undoManager = TopContainer as UndoManager;\n\n            if (closeAction != UndoCloseAction.Commit)\n            {","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/ParentUndoUnit.cs#L112-L148","documentation":"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.","triggerScenarios":"Calling Close(unit, action) passing a unit that was never opened, already closed, or belongs to a different ParentUndoUnit/UndoManager hierarchy.","commonSituations":"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.","solutions":["Verify the unit instance is the one previously passed to Open on this parent chain (reference equality, not value).","Re-check the open/close order: close deepest-first, innermost unit first.","Discard references to units after a Clear/Reset of the undo manager instead of closing them.","Wrap in try/catch for recovery if unit lifecycle cannot be tracked strictly."],"exampleFix":"// before\nif (parentUnit != null) parentUnit.Close(unit, action); // unit may be from another manager\n// after\nif (parentUnit != null && IsOpenInHierarchy(parentUnit, unit))\n{\n    parentUnit.Close(unit, action);\n}","handlingStrategy":"validation","validationCode":"bool unitBelongsToHierarchy = ReferenceEquals(parentUnit.OpenedUnit, unit)\n    || ContainsUnit(parentUnit, unit); // walk your own open-unit bookkeeping","typeGuard":"bool IsTrackedUnit(IUndoUnit u) => openedUnits.Contains(u);","tryCatchPattern":"try { parentUnit.Close(unit, action); }\ncatch (ArgumentException ex) when (ex.ParamName == \"unit\")\n{\n    // unit not open in this hierarchy: discard reference\n}","preventionTips":["Close deepest-first, innermost units first","Only close the exact instance returned from Open","Keep one undo manager per control; never mix unit hierarchies"],"tags":["wpf","undo-unit","entity-not-found","argument"],"backgroundTag":"entity-not-found","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}