dotnet/wpf · error · InvalidOperationException

throw new…

Error message

throw new InvalidOperationException(SR.CannotMoveToUnknownPosition);

What it means

When a Move notification arrives with NewStartingIndex < 0, EnumerableCollectionView cannot determine where the item(s) were moved to and throws CannotMoveToUnknownPosition. INotifyCollectionChanged requires Move events to carry a valid destination index.

Solutions

  1. Set NewStartingIndex to the post-move index when raising Move events (NotifyCollectionChangedAction.Move accepts a single index).
  2. Raise Reset when the destination index cannot be determined.
  3. Replace the Move with explicit Remove+Add events at known indices.
  4. Use ObservableCollection<T>.Move which always reports the correct index.

Example fix

// before
RaiseEvent(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, item, -1));
// after
RaiseEvent(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, item, newIndex));
Defensive patterns

Strategy: validation

Validate before calling

if (moveArgs.NewStartingIndex < 0)
    moveArgs = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);

Try / catch

try { ApplyMove(args); } catch (InvalidOperationException) { view.Refresh(); }

Prevention

When it happens

Trigger: Source collection raises NotifyCollectionChangedAction.Move with args.NewStartingIndex == -1 (unknown position), processed by ProcessCollectionChanged on a bound view.

Common situations: Custom collections implementing Move by reusing a generic constructor or defaulting indices to -1; forwarding a Move event built from incomplete information.

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


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Data/EnumerableCollectionView.cs:443

                            // replace error message with a better one
                            throw new InvalidOperationException(SR.Format(SR.AddedItemNotAtIndex, index));
                        _snapshot.RemoveAt(index);
                    }
                    break;

                case NotifyCollectionChangedAction.Replace:
                    for (int i = args.NewItems.Count - 1, index = args.NewStartingIndex + i; i >= 0; --i, --index)
                    {
                        if (!System.Windows.Controls.ItemsControl.EqualsEx(args.OldItems[i], _snapshot[index]))
                            // replace error message with a better one
                            throw new InvalidOperationException(SR.Format(SR.AddedItemNotAtIndex, index));
                        _snapshot[index] = args.NewItems[i];
                    }
                    break;

                case NotifyCollectionChangedAction.Move:
                    if (args.NewStartingIndex < 0)
                        throw new InvalidOperationException(SR.CannotMoveToUnknownPosition);

                    if (args.OldStartingIndex < args.NewStartingIndex)
                    {
                        for (int i = args.OldItems.Count - 1,
                                oldIndex = args.OldStartingIndex + i,
                                newIndex = args.NewStartingIndex + i;
                            i >= 0;
                            --i, --oldIndex, --newIndex)
                        {
                            if (!System.Windows.Controls.ItemsControl.EqualsEx(args.OldItems[i], _snapshot[oldIndex]))
                                // replace error message with a better one
                                throw new InvalidOperationException(SR.Format(SR.AddedItemNotAtIndex, oldIndex));
                            _snapshot.Move(oldIndex, newIndex);
                        }
                    }
                    else
                    {
                        for (int i = 0,

View on GitHub (pinned to 81131a70a4)