dotnet/wpf · error · InvalidOperationException
SR.CannotMoveToUnknownPosition
Error message
SR.CannotMoveToUnknownPosition
What it means
When a source collection raises a Move event, CollectionView requires a valid target index. If NewStartingIndex is negative (unknown, -1), the view cannot place the moved item and throws InvalidOperationException with CannotMoveToUnknownPosition.
Solutions
- Ensure Move events are raised with a valid non-negative NewStartingIndex
- If the new position is unknown, raise Reset instead
- Assert/validate the computed target index before raising the event
Example fix
// before OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, item, -1, oldIndex)); // after OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, item, newIndex, oldIndex));
Defensive patterns
Strategy: validation
Validate before calling
bool isValidMoveIndex(NotifyCollectionChangedEventArgs e) => e.Action != NotifyCollectionChangedAction.Move || e.NewStartingIndex >= 0;
Type guard
static bool HasKnownMoveTarget(NotifyCollectionChangedEventArgs e) => e.Action == NotifyCollectionChangedAction.Move && e.NewStartingIndex >= 0;
Try / catch
try { view.ProcessChange(e); } catch (InvalidOperationException ex) when (ex.Message.Contains("CannotMoveToUnknownPosition")) { view.Refresh(); } Prevention
- Always supply the destination index in Move notifications
- Use Reset when the target position is unknown
- Validate computed indices before raising events
When it happens
Trigger: A bound collection raises NotifyCollectionChangedAction.Move with NewStartingIndex = -1, typically from a custom collection that constructs the args without specifying the new index.
Common situations: Custom observable collections raising Move events with default/unknown index arguments; refactored collection code where the new position was computed as -1 on failure.
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.RemovedItemNotFound
- 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/b230a742b7c0d101.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/CollectionView.cs:1971
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:
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)
{View on GitHub (pinned to 81131a70a4)