dotnet/wpf · error · NotSupportedException
SR.Format(SR.UnexpectedCollectionChangeAction, e.Action)
Error message
SR.Format(SR.UnexpectedCollectionChangeAction, e.Action)
What it means
CollectionView.ProcessCollectionChanged handles Add, Remove, Replace, Move and Reset. Any other NotifyCollectionChangedAction value reaching it falls into the default case and throws NotSupportedException with UnexpectedCollectionChangeAction. Since the enum has no other standard values, this guards against corrupt or synthetic events.
Solutions
- Only raise events with valid NotifyCollectionChangedAction values (Add, Remove, Replace, Move, Reset)
- Audit custom INotifyCollectionChanged implementations for uninitialized enum fields
- Validate enum values before constructing NotifyCollectionChangedEventArgs
Example fix
// before
var action = (NotifyCollectionChangedAction)rawValue; // may be invalid
// after
if (Enum.IsDefined(typeof(NotifyCollectionChangedAction), rawValue))
var action = (NotifyCollectionChangedAction)rawValue; Defensive patterns
Strategy: validation
Validate before calling
bool isValidAction(NotifyCollectionChangedAction a) => a is NotifyCollectionChangedAction.Add or NotifyCollectionChangedAction.Remove or NotifyCollectionChangedAction.Replace or NotifyCollectionChangedAction.Move or NotifyCollectionChangedAction.Reset;
Type guard
static bool IsDefinedAction(NotifyCollectionChangedAction a) => Enum.IsDefined(typeof(NotifyCollectionChangedAction), a);
Try / catch
try { view.ProcessChange(e); } catch (NotSupportedException ex) when (ex.Message.Contains("UnexpectedCollectionChangeAction")) { view.Refresh(); } Prevention
- Initialize enum fields explicitly to a valid action
- Cast to NotifyCollectionChangedAction only after Enum.IsDefined
- Favor well-tested collection base classes over manual event raising
When it happens
Trigger: A NotifyCollectionChangedEventArgs with an out-of-range or undefined action value is passed to the view, e.g. by casting an arbitrary int to NotifyCollectionChangedAction or via reflection-based event raising.
Common situations: Testing frameworks or mocking libraries fabricating change events with invalid enum values; binary/formatter deserialization producing corrupt enum values; hand-written event args with an uninitialized enum field (0 if not assigned to a valid action).
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- SR.CannotMoveToUnknownPosition
- SR.CollectionView_NameTypeDuplicity
- SR.CollectionView_WrongType
- SR.RemovedItemNotFound
- ArgumentNullException(nameof(value))
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/20c746c73dd2b093.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/CollectionView.cs:1978
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:
throw new NotSupportedException(SR.Format(SR.UnexpectedCollectionChangeAction, e.Action));
}
}
// fix up CurrentPosition and CurrentItem after a collection change
private void AdjustCurrencyForAdd(int index)
{
// adjust current index if insertion is earlier
if (Count == 1)
_currentPosition = -1;
else if (index <= _currentPosition)
{
++_currentPosition;
if (_currentPosition < Count)
{
_currentItem = EnumerableWrapper[_currentPosition];
}
}View on GitHub (pinned to 81131a70a4)