stride3d/stride · error · InvalidOperationException

is not contained in a hierarchy.

Error message

{entity} is not contained in a hierarchy.

What it means

EntityHierarchyEditorViewModel.GetRoot(entity) walks up TransformParent links to find the hierarchy root. If the loop ends with rootEntity.TransformParent still null, the entity is not attached to any EntityHierarchyRootViewModel, meaning it is not part of a scene hierarchy, and an InvalidOperationException is thrown.

Solutions

  1. Ensure the entity is inserted into the entity hierarchy before calling GetRoot
  2. Check entity.TransformParent != null (or that it belongs to a root) before calling
  3. Re-add the detached entity to the hierarchy via the editor's insert APIs

Example fix

// before
var root = editorViewModel.GetRoot(entity); // throws if detached
// after
if (entity.TransformParent != null)
    var root = editorViewModel.GetRoot(entity);
Defensive patterns

Strategy: type-guard

Validate before calling

bool inHierarchy = entity.TransformParent != null;
if (inHierarchy) { var root = editorViewModel.GetRoot(entity); }

Type guard

bool HasHierarchyRoot(EntityViewModel e) => e.TransformParent != null;

Try / catch

try { var root = editorViewModel.GetRoot(entity); }
catch (InvalidOperationException) { /* entity is detached from the hierarchy */ }

Prevention

When it happens

Trigger: Calling GetRoot with an EntityViewModel whose TransformParent chain never reaches an EntityHierarchyRootViewModel — e.g. a detached or newly created entity not yet inserted into the hierarchy.

Common situations: Querying the hierarchy root for an entity that was created but not yet added to the scene; an entity whose parent view-model link was broken by a partial deletion.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at sources/editor/Stride.Assets.Presentation/AssetEditors/EntityHierarchyEditor/ViewModels/EntityHierarchyEditorViewModel.cs:224

            // set selection to new copied elements.
            SelectedItems.AddRange(duplicatedAssets);

            return duplicatedAssets;
        }

        [NotNull]
        public static EntityHierarchyRootViewModel GetRoot([NotNull] EntityViewModel entity)
        {
            if (entity == null) throw new ArgumentNullException(nameof(entity));
            var rootEntity = entity;
            EntityViewModel parentEntity;
            while ((parentEntity = rootEntity.TransformParent as EntityViewModel) != null)
            {
                rootEntity = parentEntity;
            }
            if (rootEntity.TransformParent == null)
                throw new InvalidOperationException($"{entity} is not contained in a hierarchy.");
            return (EntityHierarchyRootViewModel)rootEntity.TransformParent;
        }

        public void UpdateTransformations([NotNull] IReadOnlyDictionary<AbsoluteId, TransformationTRS> transformations)
        {
            using (var transaction = UndoRedoService.CreateTransaction())
            {
                foreach (var transformation in transformations)
                {
                    var element = (EntityHierarchyElementViewModel)FindPartViewModel(transformation.Key);
                    UpdateTransformations(element, transformation.Value);
                }

                UndoRedoService.SetName(transaction, "Update transformation");
            }
        }

        protected virtual void UpdateTransformations(EntityHierarchyElementViewModel element, TransformationTRS transformation)

View on GitHub (pinned to 96fad776d2)