stride3d/stride · error · InvalidOperationException

Scenes with entities cannot be removed.

Error message

Scenes with entities cannot be removed.

What it means

SceneEditorGame.RemoveScene throws this InvalidOperationException when the target scene still contains loaded entities. Scenes must be empty of entities before removal, otherwise loaded game-side objects would be orphaned.

Solutions

  1. Unload the scene's entities before calling RemoveScene.
  2. Track loaded entities per scene and unload them in cleanup logic.
  3. Catch InvalidOperationException and report that the scene must be emptied first.

Example fix

// before
sceneEditorGame.RemoveScene(sceneId); // entities still loaded
// after
if (sceneEditorGame.GetScene(sceneId).Entities.Count == 0)
    sceneEditorGame.RemoveScene(sceneId);
else
    UnloadSceneEntitiesThenRemove(sceneId);
Defensive patterns

Strategy: validation

Validate before calling

var scene = game.GetScene(sceneId);
if (scene == null || scene.Entities.Count > 0) UnloadEntitiesAndRetry(sceneId);

Type guard

bool IsEmptyScene(Guid id) { var s = game.GetScene(id); return s != null && s.Children.Count == 0 && s.Entities.Count == 0; }

Try / catch

try { game.RemoveScene(sceneId); } catch (InvalidOperationException ex) when (ex.Message.Contains("entities")) { UnloadSceneEntities(sceneId); game.RemoveScene(sceneId); }

Prevention

When it happens

Trigger: Calling RemoveScene on a scene whose Entities collection is non-empty (entities were loaded via LoadEntities and never unloaded).

Common situations: Deleting a scene without first unloading its entities; editor sessions where entity unloading failed or was skipped.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at sources/editor/Stride.Assets.Presentation/AssetEditors/SceneEditor/Game/SceneEditorGame.cs:91

        /// <summary>
        /// Removes the existing scene identified by <paramref name="sceneId"/>.
        /// </summary>
        /// <param name="sceneId">The identifier of the scene to remove.</param>
        /// <remarks>
        /// The scene must be empty, i.e. its child scenes must have been removed first and its entities unloaded.
        /// </remarks>
        public void RemoveScene(Guid sceneId)
        {
            if (sceneId == Guid.Empty)
                throw new InvalidOperationException($"{nameof(sceneId)} cannot be {nameof(Guid.Empty)}.");

            EnsureContentScene();

            var scene = GetScene(sceneId);
            if (scene.Children.Count > 0)
                throw new InvalidOperationException("Scenes with child scenes cannot be removed.");
            if (scene.Entities.Count > 0)
                throw new InvalidOperationException("Scenes with entities cannot be removed.");

            SceneRemoved?.Invoke(scene);
            RemoveSceneFromParent(scene);
            scenes.Remove(sceneId);
        }

        /// <inheritdoc/>
        public override Entity FindSubEntity(Guid sceneId, Guid entityId)
        {
            EnsureContentScene();

            Scene scene;
            if (scenes.TryGetValue(sceneId, out scene))
            {
                Entity entity;
                // Note: special case of the virtual anchor (sceneID == entityId), own by the parent scene
                if (sceneId == entityId)
                    entity = scene.Parent?.FindSubEntity(entityId);

View on GitHub (pinned to 96fad776d2)