stride3d/stride · error · InvalidOperationException

The SessionViewModel class can be instanced only once.

Error message

The SessionViewModel class can be instanced only once.

What it means

SessionViewModel enforces a singleton pattern via a static Instance field. The constructor throws InvalidOperationException if Instance is already set, because the class can only be instantiated once per editor process. After construction it assigns Instance = this.

Solutions

  1. Dispose/close the existing SessionViewModel (which should null Instance) before creating a new one.
  2. Keep a single app-wide SessionViewModel and reuse it instead of constructing new ones.
  3. In tests, reset the singleton (dispose and clear Instance) in test teardown.
  4. Catch InvalidOperationException to detect an existing session and route to the existing instance.

Example fix

// before
var newSession = SessionViewModel.CreateInstance(provider, logger, session, editor); // Instance still set
// after
oldSession.Dispose(); // clears Instance
var newSession = SessionViewModel.CreateInstance(provider, logger, session, editor);
Defensive patterns

Strategy: validation

Validate before calling

if (SessionViewModel.Instance != null)
    throw new InvalidOperationException("SessionViewModel already exists; dispose it first");

Try / catch

try { session = SessionViewModel.CreateInstance(sp, log, ps, editor); }
catch (InvalidOperationException) { session = SessionViewModel.Instance; /* reuse singleton */ }

Prevention

When it happens

Trigger: Constructing (via CreateInstance) a second SessionViewModel while the previous instance is still alive and Instance is non-null.

Common situations: Opening a second editor session or reloading a session without disposing the first; unit tests that construct SessionViewModel multiple times without cleanup.

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/0aac72d5531ae50d. Report an issue: GitHub.

Appendix: source

Thrown at sources/editor/Stride.Core.Assets.Editor/ViewModel/SessionViewModel.cs:563

            var documentationService = ServiceProvider.Get<UserDocumentationService>();
            foreach (var packageAssembly in LocalPackages.SelectMany(p => p.LoadedAssemblies))
            {
                if (packageAssembly.Assembly != null)
                    Task.Run(() => documentationService.CacheAssemblyDocumentation(packageAssembly.Assembly));
            }
        }

        private SessionViewModel(IViewModelServiceProvider serviceProvider, ILogger logger, [NotNull] PackageSession session, [NotNull] EditorViewModel editor)
            : base(serviceProvider)
        {
            if (editor == null) throw new ArgumentNullException(nameof(editor));
            if (editor.Session != null) throw new InvalidOperationException("Unable to have two sessions at the same time");

            Editor = editor;
            this.session = session;

            if (Instance != null)
                throw new InvalidOperationException("The SessionViewModel class can be instanced only once.");

            Instance = this;

            // Initialize the dirtiable manager for all our dirtiable objects
            undoRedoService = ServiceProvider.Get<IUndoRedoService>();

            // Gather all data from plugins
            PluginService.RegisterSession(this, logger);

            // Initialize the undo/redo debug view model
            undoRedoStackPage = EditorDebugTools.CreateUndoRedoDebugPage(undoRedoService, "Undo/redo stack");
            ActionHistory = new ActionHistoryViewModel(this);

            // Initialize the node container used for asset properties
            AssetNodeContainer = new SessionNodeContainer(this) { NodeBuilder = { NodeFactory = new AssetNodeFactory() } };

            // Initialize the view model that will manage the properties of the assets selected on the main asset view
            AssetViewProperties = new SessionObjectPropertiesViewModel(this);

View on GitHub (pinned to 96fad776d2)