stride3d/stride · error · InvalidOperationException

Scenes with child scenes cannot be removed.

Error message

Scenes with child scenes cannot be removed.

What it means

SceneEditorGame.RemoveScene throws this InvalidOperationException when the target scene still has child scenes. The API requires bottom-up deletion: children must be removed first, as noted in the method's remarks.

Solutions

  1. Recursively remove child scenes before removing the parent.
  2. Iterate scene collections deepest-first when cleaning up.
  3. Catch InvalidOperationException and prompt the user to delete children first.

Example fix

// before
sceneEditorGame.RemoveScene(sceneId); // has children
// after
void RemoveRecursive(Guid id) {
    var scene = sceneEditorGame.GetScene(id);
    foreach (var child in scene.Children.ToList())
        RemoveRecursive(child.Id);
    sceneEditorGame.RemoveScene(id);
}
Defensive patterns

Strategy: try-catch

Validate before calling

var scene = game.GetScene(sceneId);
if (scene != null && scene.Children.Count > 0) RemoveChildrenFirst(scene);

Try / catch

try { game.RemoveScene(sceneId); } catch (InvalidOperationException ex) when (ex.Message.Contains("child scenes")) { DeleteChildrenRecursively(sceneId); game.RemoveScene(sceneId); }

Prevention

When it happens

Trigger: Calling RemoveScene on a scene whose Children collection is non-empty.

Common situations: Deleting a parent scene in a hierarchy UI without deleting descendants; bulk cleanup that iterates scenes in arbitrary order.

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/2eefa02b4777b6ce. Report an issue: GitHub.

Appendix: source

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

        }

        /// <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

View on GitHub (pinned to 96fad776d2)