stride3d/stride · error · NotSupportedException

Replace, Move and Reset are not supported on this…

Error message

Replace, Move and Reset are not supported on this collection.

What it means

EntityHierarchyItemViewModel.SubEntityCollectionChanged handles Add and Remove collection-change notifications only; Replace, Move and Reset are explicitly not supported by this view-model collection, and NotSupportedException is thrown. The underlying entity hierarchy never produces those actions by design.

Solutions

  1. Express Replace as Remove followed by Add
  2. Express Move as Remove then Add at the target index (or use dedicated editor reorder APIs)
  3. Avoid Clear()/Reset; remove items individually so Remove notifications are raised

Example fix

// before
subEntities.Move(2, 0); // triggers Move notification -> throws
// after
var item = subEntities[2];
subEntities.RemoveAt(2);
subEntities.Insert(0, item);
Defensive patterns

Strategy: try-catch

Validate before calling

// express batch edits as Add/Remove only
foreach (var item in itemsToRemove) subEntities.Remove(item);

Try / catch

try { collectionMoveLogic(); }
catch (NotSupportedException) { /* fall back to remove+insert */ }

Prevention

When it happens

Trigger: Raising a CollectionChanged event with Replace, Move, or Reset actions on the sub-entities collection, typically from custom code that manipulates the collection directly with ObservableCollection APIs like Move() or Clear() with Reset semantics.

Common situations: Custom tooling that calls collection.Move() or resets the collection; binding layers that trigger Reset notifications; replacing an entity in place instead of removing and re-adding it.

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/4ad198bbb57fa0e4. Report an issue: GitHub.

Appendix: source

Thrown at sources/editor/Stride.Assets.Presentation/AssetEditors/EntityHierarchyEditor/ViewModels/EntityHierarchyItemViewModel.cs:375

                            AddItem(newItem);
                        else
                            InsertItem(addIndex++, newItem);
                    }
                    break;
                case NotifyCollectionChangedAction.Remove:
                    var delIndex = offset + e.OldStartingIndex;
                    foreach (EntityHierarchyItemViewModel oldItem in e.OldItems)
                    {
                        if (e.OldStartingIndex < 0)
                            RemoveItem(oldItem);
                        else
                            RemoveItemAt(delIndex);
                    }
                    break;
                case NotifyCollectionChangedAction.Replace:
                case NotifyCollectionChangedAction.Move:
                case NotifyCollectionChangedAction.Reset:
                    throw new NotSupportedException("Replace, Move and Reset are not supported on this collection.");
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        /// <summary>
        /// Gets how this item accepts the given children.
        /// </summary>
        /// <param name="children">The children to add or to insert.</param>
        /// <param name="checkSameParent">True to give a no-op when a child is already a child of this item.</param>
        /// <param name="modifiers">The modifier keys currently active.</param>
        /// <param name="index">The index at which the children go.</param>
        /// <param name="message">The feedback message that can be used in the user interface.</param>
        /// <remarks>
        /// A rejected child stops the check immediately. If no child is rejected and no child is accepted, but a child
        /// changes nothing, the result is <see cref="DropAcceptance.NoOp"/>. Therefore a selection that mixes items
        /// which are already here with items which are not stays accepted, and it moves only the second group.
        /// </remarks>

View on GitHub (pinned to 96fad776d2)