stride3d/stride · error · ArgumentException

entity must contain a non-null asset entity.

Error message

entity must contain a non-null asset entity.

What it means

EntityViewModel's constructor requires the supplied EntityDesign to already carry a non-null Entity instance, since the view model immediately builds node bindings against entityDesign.Entity (Name, Components). If the entity is null, the base constructor call itself (GetOrCreateChildPartDesigns / base(..., entityDesign.Entity)) would fail downstream, so the constructor fails fast with an ArgumentException naming the offending parameter.

Solutions

  1. Assign entityDesign.Entity = new Entity() (or the intended instance) before constructing the EntityViewModel.
  2. Check entityDesign?.Entity == null at the call site and construct/populate the entity first.
  3. If the design comes from deserialization, verify the source asset part actually contains an entity definition and was fully loaded.

Example fix

// before
var design = new EntityDesign();
var vm = new EntityViewModel(editor, hierarchy, design); // throws
// after
var design = new EntityDesign(new Entity { Name = "MyEntity" });
var vm = new EntityViewModel(editor, hierarchy, design);
Defensive patterns

Strategy: validation

Validate before calling

if (entityDesign == null || entityDesign.Entity == null)
    throw new ArgumentException(nameof(entityDesign), "EntityDesign must wrap a non-null Entity before creating an EntityViewModel.");

Type guard

bool IsValidDesign(EntityDesign d) => d?.Entity != null;

Try / catch

try { var vm = new EntityViewModel(editor, asset, design); }
catch (ArgumentException ex) when (ex.ParamName == nameof(entityDesign)) { log.Error("EntityDesign has null Entity", ex); }

Prevention

When it happens

Trigger: Calling new EntityViewModel(editor, asset, entityDesign) where entityDesign.Entity == null — e.g. constructing an EntityDesign with its default/empty constructor or deserializing a partial asset part definition and passing it straight to the view model.

Common situations: Plugin or custom tooling that creates EntityDesign objects programmatically to inject entities into an entity hierarchy editor; code paths that build design objects before assigning the Entity property; upgrading Stride versions where EntityDesign population changed.

Related errors


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

Appendix: source

Thrown at sources/editor/Stride.Assets.Presentation/AssetEditors/EntityHierarchyEditor/ViewModels/EntityViewModel.cs:52

    [DebuggerDisplay("Entity = {Name}")]
    public sealed class EntityViewModel : EntityHierarchyElementViewModel, IEditorDesignPartViewModel<EntityDesign, Entity>, IIsEditableViewModel, IDisposable, IAddChildrenPropertiesProviderViewModel
    {
        private EntityHierarchyElementChangePropagator propagator;

        // TODO These models should be pluggable later
        private readonly ModelComponentViewModel modelComponent;
        private readonly ParticleSystemComponentViewModel particleComponent;
        private readonly CameraComponentViewModel cameraComponent;

        private readonly MemberGraphNodeBinding<string> nameNodeBinding;
        private readonly ObjectGraphNodeBinding<EntityComponentCollection> componentsNodeBinding;
        private readonly IObjectNode transformationNode;
        private PrefabViewModel sourcePrefab;

        public EntityViewModel([NotNull] EntityHierarchyEditorViewModel editor, [NotNull] EntityHierarchyViewModel asset, [NotNull] EntityDesign entityDesign)
            : base(editor, asset, GetOrCreateChildPartDesigns((EntityHierarchyAssetBase)asset.Asset, entityDesign), entityDesign.Entity)
        {
            if (entityDesign.Entity == null) throw new ArgumentException(@"entity must contain a non-null asset entity.", nameof(entityDesign));

            EntityDesign = entityDesign;

            var assetNode = Editor.NodeContainer.GetOrCreateNode(entityDesign.Entity);
            nameNodeBinding = new MemberGraphNodeBinding<string>(assetNode[nameof(Entity.Name)], nameof(Name), OnPropertyChanging, OnPropertyChanged, Editor.UndoRedoService);
            componentsNodeBinding = new ObjectGraphNodeBinding<EntityComponentCollection>(assetNode[nameof(Entity.Components)].Target, nameof(Components), OnPropertyChanging, OnPropertyChanged, Editor.UndoRedoService, false);

            modelComponent = new ModelComponentViewModel(ServiceProvider, this);
            particleComponent = new ParticleSystemComponentViewModel(ServiceProvider, this);
            cameraComponent = new CameraComponentViewModel(ServiceProvider, this);
            transformationNode = Editor.NodeContainer.GetNode(AssetSideEntity.Transform)[nameof(TransformComponent.Children)].Target;
            transformationNode.ItemChanging += TransformChildrenChanging;
            transformationNode.ItemChanged += TransformChildrenChanged;
            RenameCommand = new AnonymousCommand(ServiceProvider, () => IsEditing = true);
            FocusOnEntityCommand = new AnonymousCommand(ServiceProvider, FocusOnEntity);

            UpdateSourcePrefab();
            var basePrefabNode = Editor.NodeContainer.GetNode(EntityDesign)[nameof(EntityDesign.Base)];

View on GitHub (pinned to 96fad776d2)