dotnet/wpf · error · NotSupportedException
SR.Format(SR.UnexpectedCollectionChangeAction, e.Action)
Error message
SR.Format(SR.UnexpectedCollectionChangeAction, e.Action)
What it means
ListCollectionView.ProcessCollectionChange encountered a NotifyCollectionChangedAction value outside Add/Remove/Replace/Move/Reset when replaying an underlying-collection change into its shadow copy. Since .NET has no other defined actions, this indicates a corrupt or custom-injected event argument. It is thrown as NotSupportedException to signal the view cannot process the change.
Solutions
- Fix the custom INotifyCollectionChanged source to only raise the five standard NotifyCollectionChangedAction values.
- Construct event args via NotifyCollectionChangedEventArgs.Add/Remove/Replace/Move/Reset factories instead of custom subclasses.
- Catch NotSupportedException around collection mutations if the event source is out of your control, and resync the view by calling Refresh().
Example fix
// before (custom collection) OnCollectionChanged(new NotifyCollectionChangedEventArgs((NotifyCollectionChangedAction)99)); // after OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
Defensive patterns
Strategy: type-guard
Validate before calling
if (!Enum.IsDefined(typeof(NotifyCollectionChangedAction), args.Action)) throw new InvalidOperationException("Invalid collection change action"); Type guard
bool IsValidAction(NotifyCollectionChangedAction a) => a is NotifyCollectionChangedAction.Add or NotifyCollectionChangedAction.Remove or NotifyCollectionChangedAction.Replace or NotifyCollectionChangedAction.Move or NotifyCollectionChangedAction.Reset;
Try / catch
try { view.Refresh(); } catch (NotSupportedException) { view.Refresh(); /* resync view from source */ } Prevention
- Only raise the five standard NotifyCollectionChangedAction values
- Use NotifyCollectionChangedEventArgs static factory methods
- Never cast arbitrary ints to NotifyCollectionChangedAction without Enum.IsDefined
When it happens
Trigger: A CollectionChanged handler path in ProcessCollectionChange receives e.Action not equal to Add, Remove, Replace, Move, or Reset — practically only from a custom INotifyCollectionChanged implementation passing an invalid/cast enum value.
Common situations: Custom observable collections that manually raise CollectionChanged with hand-crafted or unvalidated NotifyCollectionChangedEventArgs; aggressive enum casts like (NotifyCollectionChangedAction)99; interop code reusing event args across libraries.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- SR.BindingListCannotCustomFilter
- SR.Format(SR.UnexpectedCollectionChangeAction, e.Action)
- SR.RangeActionsNotSupported
- By default, ToolTip property does not support ToolTip…
- Cannot convert from type.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/5188d547740eee97.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/ListCollectionView.cs:2411
{
// allow the ShadowCollection to throw the IndexOutOfRangeException
// if the item is not found.
tempIndex = ShadowCollection.IndexOf(e.OldItems[0]);
ShadowCollection[tempIndex] = e.NewItems[0];
}
break;
case NotifyCollectionChangedAction.Move:
tempIndex = e.OldStartingIndex;
if (tempIndex < 0)
{
tempIndex = ShadowCollection.IndexOf(e.NewItems[0]);
}
ShadowCollection.RemoveAt(tempIndex);
ShadowCollection.Insert(e.NewStartingIndex, e.NewItems[0]);
break;
default:
throw new NotSupportedException(SR.Format(SR.UnexpectedCollectionChangeAction, e.Action));
}
}
// returns true if this ListCollectionView has sort descriptions,
// without tripping off lazy creation of .SortDescriptions collection
internal bool HasSortDescriptions
{
get { return ((_sort != null) && (_sort.Count > 0)); }
}
// return an appropriate comparer. Common logic used by ListCollectionView
// and by CollectionViewGroupInternal.
internal static IComparer PrepareComparer(IComparer customSort, SortDescriptionCollection sort, Func<object, CollectionView> lazyGetCollectionView, object state)
{
if (customSort != null)
{
return customSort;
}View on GitHub (pinned to 81131a70a4)