dotnet/wpf · error · InvalidOperationException

SR.Format(SR.MemberNotAllowedDuringAddOrEdit, "RemoveAt")

Error message

SR.Format(SR.MemberNotAllowedDuringAddOrEdit, "RemoveAt")

What it means

RemoveAt(int) removes an item from the underlying collection via the view, but it is rejected with InvalidOperationException while an AddNew or EditItem transaction is in progress. Mutating the collection during an open transaction would corrupt the view's tracking of the new/edited item.

Solutions

  1. Call CommitEdit()/CancelEdit() and CommitNew()/CancelNew() before RemoveAt.
  2. Guard with !view.IsEditingItem && !view.IsAddingNew before removing.
  3. Cancel the in-flight transaction explicitly when the item being removed is the new/edited one.
  4. Use CollectionView's CanRemove check (base CollectionView.CanRemove) before calling RemoveAt.

Example fix

// before
view.RemoveAt(index);

// after
if (!view.IsEditingItem && !view.IsAddingNew && view.CanRemove)
    view.RemoveAt(index);
else
    view.CancelEdit(); view.CancelNew(); // close transactions, then retry
Defensive patterns

Strategy: validation

Validate before calling

// C#
if (!view.IsEditingItem && !view.IsAddingNew && view.CanRemove)
    view.RemoveAt(index);

Type guard

bool CanRemoveAt(IEditableCollectionView v) => !v.IsEditingItem && !v.IsAddingNew;

Try / catch

try { view.RemoveAt(index); }
catch (InvalidOperationException ex) { Log.Warn("RemoveAt during add/edit", ex); view.CancelEdit(); view.CancelNew(); }

Prevention

When it happens

Trigger: Calling RemoveAt(index) when IsEditingItem or IsAddingNew is true — e.g. removing the currently-being-added or currently-being-edited row programmatically.

Common situations: A delete button handler that does not check for open add/edit transactions; DataGrid delete key pressed while a new row or cell edit is open; automation/scripts removing rows during batch edits.

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


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/BindingListCollectionView.cs:872

        /// <summary>
        /// Return true if the view supports <seealso cref="Remove"/> and
        /// <seealso cref="RemoveAt"/>.
        /// </summary>
        public bool CanRemove
        {
            get { return !IsEditingItem && !IsAddingNew && InternalList.AllowRemove; }
        }

        /// <summary>
        /// Remove the item at the given index from the underlying collection.
        /// The index is interpreted with respect to the view (not with respect to
        /// the underlying collection).
        /// </summary>
        public void RemoveAt(int index)
        {
            if (IsEditingItem || IsAddingNew)
                throw new InvalidOperationException(SR.Format(SR.MemberNotAllowedDuringAddOrEdit, "RemoveAt"));
            VerifyRefreshNotDeferred();

            RemoveImpl(GetItemAt(index), index);
        }

        /// <summary>
        /// Remove the given item from the underlying collection.
        /// </summary>
        public void Remove(object item)
        {
            if (IsEditingItem || IsAddingNew)
                throw new InvalidOperationException(SR.Format(SR.MemberNotAllowedDuringAddOrEdit, "Remove"));
            VerifyRefreshNotDeferred();

            int index = InternalIndexOf(item);
            if (index >= 0)
            {
                RemoveImpl(item, index);

View on GitHub (pinned to 81131a70a4)