stride3d/stride · critical · InvalidOperationException
The StrideAssetsViewModel class can be instanced only once.
Error message
The StrideAssetsViewModel class can be instanced only once.
What it means
StrideAssetsViewModel is a process-wide singleton for the asset editor session. Its constructor throws InvalidOperationException if a static Instance already exists, because duplicate instances would create two competing views of the same asset session. Note the throw happens AFTER constructing CodeViewModel but the TaskCompletionSource `instance.TrySetResult(this)` runs after the check, so a second construction aborts before satisfying the instance task.
Solutions
- Reuse the existing instance via `StrideAssetsViewModel.InstanceTask` (await it) instead of constructing a new one.
- Guard construction with `if (StrideAssetsViewModel.Instance == null)` before instantiating.
- In tests, create the view model in a fresh AppDomain/assembly-reload context or accept it as a shared fixture.
- For multi-session needs, refactor to hold per-session view models instead of relying on the singleton.
Example fix
// before var vm = new StrideAssetsViewModel(session); // after var vm = await StrideAssetsViewModel.InstanceTask; // or: if (StrideAssetsViewModel.Instance != null) return;
Defensive patterns
Strategy: fallback
Validate before calling
if (StrideAssetsViewModel.Instance != null)
return await StrideAssetsViewModel.InstanceTask;
var vm = new StrideAssetsViewModel(session); Prevention
- Always acquire the assets view model through StrideAssetsViewModel.InstanceTask, never via direct construction in feature code.
- Centralize construction in one composition-root location.
- In tests, treat it as a shared singleton fixture or isolate per AppDomain.
When it happens
Trigger: Constructing `new StrideAssetsViewModel(...)` a second time in the same AppDomain, e.g. re-running editor startup code, creating a second assets view/window, or unit tests that build the view model per test without resetting the static Instance.
Common situations: Opening a second editor window for the same session; plugin/extension code initializing the assets view model independently; test fixtures that don't isolate static state; hot-reload scenarios re-running initialization.
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
- The EditorViewModel class can be instanced only once.
- No multi value converter has been set.
- An instance of WindowManager is already existing.
- Cannot register new platforms. RegisterSupportedPlatforms ca
- The service [{service.GetType().Name}] requires a service of
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/ff15a0cc460023fc.
Report an issue: GitHub.
Appendix: source
Thrown at sources/editor/Stride.Assets.Presentation/ViewModel/StrideAssetsViewModel.cs:21
using System;
using System.Threading.Tasks;
using Stride.Core.Assets.Editor.ViewModel;
using Stride.Core.Presentation.ViewModels;
namespace Stride.Assets.Presentation.ViewModel
{
public class StrideAssetsViewModel : DispatcherViewModel
{
private static readonly TaskCompletionSource<StrideAssetsViewModel> instance = new TaskCompletionSource<StrideAssetsViewModel>();
public StrideAssetsViewModel(SessionViewModel session) : base(session.ServiceProvider)
{
Session = session;
Code = new CodeViewModel(this);
if (Instance != null)
throw new InvalidOperationException($"The {nameof(StrideAssetsViewModel)} class can be instanced only once.");
instance.TrySetResult(this);
Instance = this;
}
public static Task<StrideAssetsViewModel> InstanceTask => instance.Task;
public static StrideAssetsViewModel Instance { get; private set; }
public SessionViewModel Session { get; }
public CodeViewModel Code { get; }
}
}
View on GitHub (pinned to 96fad776d2)