stride3d/stride · error · NotSupportedException

Move is not supported by the undo stack.

Error message

Move is not supported by the undo stack.

What it means

When undoing (or redoing the inverse of) a recorded change, CollectionChangeOperation.Undo handles Add/Remove/Replace but throws NotSupportedException for Move and Reset actions — these were never intended to be recorded by the undo stack.

Solutions

  1. Avoid operations that raise Move on undo-tracked lists; express moves as Remove+Add
  2. Ensure only Add/Remove/Replace actions get recorded into CollectionChangeOperation
  3. Wrap Undo in try-catch for NotSupportedException and skip/invalidate the operation

Example fix

// before
list.Move(3, 0); // Move recorded, Undo throws
// after
var item = list[3];
list.RemoveAt(3);
list.Insert(0, item); // Remove + Add, undoable
Defensive patterns

Strategy: try-catch

Validate before calling

if (e.Action is NotifyCollectionChangedAction.Move or NotifyCollectionChangedAction.Reset) return; // don't record

Type guard

bool IsUndoRecordable(NotifyCollectionChangedAction a) => a is not (NotifyCollectionChangedAction.Move or NotifyCollectionChangedAction.Reset);

Try / catch

try { operation.Undo(); } catch (NotSupportedException) { undoStack.Clear(); /* history invalidated */ }

Prevention

When it happens

Trigger: An undo/redo pass encounters a recorded operation whose ActionToUndo is Move (or Reset), i.e. the operation was created from args with those actions before reaching Undo.

Common situations: Undoing after a drag-reorder (Move) on a tracked list; mixing collections that emit Move/Reset events into an undo-tracked session.

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


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/a45a016d270fa1cd. Report an issue: GitHub.

Appendix: source

Thrown at sources/presentation/Stride.Core.Presentation/Dirtiables/CollectionChangeOperation.cs:114

                ActionToUndo = NotifyCollectionChangedAction.Add;
                foreach (var item in items)
                {
                    list.Insert(index + i, item);
                    ++i;
                }
                break;
            case NotifyCollectionChangedAction.Replace:
                var replacedItems = new List<object>();
                foreach (var item in items)
                {
                    replacedItems.Add(list[index + i]);
                    list[index + i] = item;
                    ++i;
                }
                items = replacedItems;
                break;
            case NotifyCollectionChangedAction.Move:
                throw new NotSupportedException("Move is not supported by the undo stack.");
            case NotifyCollectionChangedAction.Reset:
                throw new NotSupportedException("Reset is not supported by the undo stack.");
        }
    }

    /// <inheritdoc/>
    protected override void Redo()
    {
        // Once we have un-done, the previous value is updated so Redo is just Undoing the Undo
        Undo();
    }
}

View on GitHub (pinned to 96fad776d2)