dotnet/wpf · error · InvalidOperationException
SR.AddedItemNotInCollection
Error message
SR.AddedItemNotInCollection
What it means
An Add notification did not specify an index (-1), so ListCollectionView searched the source list with IndexOf and did not find the announced item at all. It throws InvalidOperationException with SR.AddedItemNotInCollection because the 'added' item is not actually present in the source.
Solutions
- Insert the item into the source collection BEFORE raising the Add event.
- Raise the event with the actual index instead of -1 to skip IndexOf.
- Verify the same object instance (or a value-equal one per the collection's comparer) is in the source list.
- If the item genuinely is not in the collection, raise Reset or no event at all.
Example fix
// before (event before mutation) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, -1)); Items.Add(item); // after Items.Add(item); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, Items.Count - 1));
Defensive patterns
Strategy: validation
Validate before calling
if (args.Action == NotifyCollectionChangedAction.Add && args.NewStartingIndex == -1 && !sourceList.Contains(args.NewItems[0])) { /* item missing; raise Reset after inserting */ } Try / catch
try { /* process add */ } catch (InvalidOperationException) { view.Refresh(); } Prevention
- Insert the item into the source list before raising the Add event
- Ensure the announced item instance exists in the bound collection
- Raise events with an explicit index when the position is known
- Never fire Add events for items added to a different collection instance
When it happens
Trigger: Raising NotifyCollectionChangedAction.Add with NewStartingIndex == -1 for an item that was never inserted into (or was later removed from) the underlying IList — the IndexOf(item) fallback returns -1.
Common situations: Event raised before the actual insert completed; item removed between raise and handling; adding an item to a filtered copy rather than the real source collection; EqualsEx/object identity mismatch so IndexOf can't locate an 'equal' item.
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
- SR.AddedItemNotAtIndex (formatted with index)
- SR.BindingListCannotCustomFilter
- SR.BindingListCanOnlySortByOneProperty
- SR.CannotMoveToUnknownPosition
- SR.CannotMoveToUnknownPosition
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/c5751e3df1855b21.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/ListCollectionView.cs:2680
IList ilFull = (AllowsCrossThreadChanges ? ShadowCollection : SourceCollection) as IList;
// validate input
if (index < -1 || index > ilFull.Count)
throw new InvalidOperationException(SR.Format(SR.CollectionChangeIndexOutOfRange, index, ilFull.Count));
if (action == NotifyCollectionChangedAction.Add)
{
if (index >= 0)
{
if (!System.Windows.Controls.ItemsControl.EqualsEx(item, ilFull[index]))
throw new InvalidOperationException(SR.Format(SR.AddedItemNotAtIndex, index));
}
else
{
// event didn't specify index - determine it the hard way
index = ilFull.IndexOf(item);
if (index < 0)
throw new InvalidOperationException(SR.AddedItemNotInCollection);
}
}
// if there's no sort or filter, use the index into the full array
if (!UsesLocalArray)
{
if (IsAddingNew)
{
if (NewItemPlaceholderPosition != NewItemPlaceholderPosition.None &&
index > _newItemIndex)
{
--index; // the new item has been artificially moved elsewhere
}
}
return (index < 0) ? index : index + delta;
}
View on GitHub (pinned to 81131a70a4)