dotnet/wpf · error · InvalidOperationException
SR.RemovedItemNotFound
Error message
SR.RemovedItemNotFound
What it means
CollectionView.ProcessCollectionChanged validates INotifyCollectionChanged events before applying them. A Remove event must carry the starting index of the removed item; when OldStartingIndex is negative (Unknown/-1) the view cannot determine what was removed. The library throws InvalidOperationException because the source collection raised a malformed change event.
Solutions
- Fix the source collection to raise Remove events with a valid, non-negative OldStartingIndex
- If the index is truly unknown, raise Reset instead of Remove
- Use ObservableCollection (or derive from it) instead of hand-rolled INotifyCollectionChanged implementations
- Verify no code constructs NotifyCollectionChangedEventArgs.Remove with -1 as the index
Example fix
// before collection.OnCollectionChanged(NotifyCollectionChangedAction.Remove, item, -1); // after collection.OnCollectionChanged(NotifyCollectionChangedAction.Remove, item, indexToRemoveAt);
Defensive patterns
Strategy: validation
Validate before calling
bool isValidRemove(NotifyCollectionChangedEventArgs e) => e.Action != NotifyCollectionChangedAction.Remove || (e.OldItems?.Count == 1 && e.OldStartingIndex >= 0);
Type guard
static bool HasKnownRemoveIndex(NotifyCollectionChangedEventArgs e) => e.Action == NotifyCollectionChangedAction.Remove && e.OldStartingIndex >= 0;
Try / catch
try { view.RefreshOrProcessChange(e); } catch (InvalidOperationException ex) when (ex.Message.Contains("RemovedItemNotFound")) { view.Refresh(); } Prevention
- Use ObservableCollection rather than hand-rolled INotifyCollectionChanged implementations
- Never construct change args with unknown indices; prefer Reset when the index is unavailable
- Unit-test custom collections against a CollectionView consumer
When it happens
Trigger: A collection bound to a CollectionView raises NotifyCollectionChangedAction.Remove with Action=Remove but NewStartingIndex/OldStartingIndex set to -1 (e.g. built via NotifyCollectionChangedEventHandler args manually or a custom ObservableCollection implementation that reports unknown index).
Common situations: Custom observable collections that construct NotifyCollectionChangedEventArgs with NotifyCollectionChangedAction.Reset semantics but send Remove; third-party collection implementations that don't track indices; manual raising of CollectionChanged events with default (unknown) index arguments.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- SR.CannotMoveToUnknownPosition
- SR.CollectionView_NameTypeDuplicity
- SR.CollectionView_WrongType
- SR.Format(SR.UnexpectedCollectionChangeAction, e.Action)
- ArgumentNullException(nameof(value))
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/f41b7313a43ee1f4.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/CollectionView.cs:1959
_tempChangeLog = s_emptyList;
return null;
}
private void ValidateCollectionChangedEventArgs(NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
if (e.NewItems.Count != 1)
throw new NotSupportedException(SR.RangeActionsNotSupported);
break;
case NotifyCollectionChangedAction.Remove:
if (e.OldItems.Count != 1)
throw new NotSupportedException(SR.RangeActionsNotSupported);
if (e.OldStartingIndex < 0)
throw new InvalidOperationException(SR.RemovedItemNotFound);
break;
case NotifyCollectionChangedAction.Replace:
if (e.NewItems.Count != 1 || e.OldItems.Count != 1)
throw new NotSupportedException(SR.RangeActionsNotSupported);
break;
case NotifyCollectionChangedAction.Move:
if (e.NewItems.Count != 1)
throw new NotSupportedException(SR.RangeActionsNotSupported);
if (e.NewStartingIndex < 0)
throw new InvalidOperationException(SR.CannotMoveToUnknownPosition);
break;
case NotifyCollectionChangedAction.Reset:
break;
default:View on GitHub (pinned to 81131a70a4)