{"record":{"id":"8b7575a3e4c593f7","repo":"dotnet/wpf","slug":"sr-undonoopenunit","errorCode":null,"errorMessage":"SR.UndoNoOpenUnit","messagePattern":"SR\\.UndoNoOpenUnit","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/ParentUndoUnit.cs","lineNumber":114,"sourceCode":"        /// IParentUndoUnit to close.  If NULL, this unit's OpenedUnit is closed.\n        /// </param>\n        /// <param name=\"closeAction\">\n        /// </param>\n        /// <exception cref=\"InvalidOperationException\">\n        /// Thrown if no undo unit is currently open\n        /// </exception>\n        /// <exception cref=\"ArgumentNullException\">\n        /// Thrown if unit is null\n        /// </exception>\n        public virtual void Close(IParentUndoUnit unit, UndoCloseAction closeAction)\n        {\n            UndoManager undoManager;\n\n            ArgumentNullException.ThrowIfNull(unit);\n\n            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","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/ParentUndoUnit.cs#L96-L132","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nparentUndoUnit.Close(unit, undoCloseAction);\n// after\nif (parentUndoUnit.OpenedUnit == unit)\n{\n    parentUndoUnit.Close(unit, undoCloseAction);\n}","handlingStrategy":"validation","validationCode":"if (unit == null) throw new ArgumentNullException(nameof(unit));\nbool closable = parentUnit.OpenedUnit != null;","typeGuard":"bool HasOpenUnit(ParentUndoUnit p) => p?.OpenedUnit != null;","tryCatchPattern":"try { parentUnit.Close(unit, action); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"no open unit\"))\n{\n    // unbalanced close: drop the stale reference\n}","preventionTips":["Track open/close pairing explicitly in transaction objects","Never close a unit twice","Invalidate held unit references after UndoManager.Clear/Reset"],"tags":["wpf","undo-unit","invalid-state","unbalanced-open-close"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}