stride3d/stride · error · InvalidOperationException
An instance of WindowManager is already existing.
Error message
An instance of WindowManager is already existing.
What it means
WindowManager is a process-wide singleton: a static initialized flag prevents a second instantiation because it installs a native WinEvent hook that cannot coexist with another manager. The constructor throws InvalidOperationException if an instance was already created.
Solutions
- Create WindowManager once and reuse the existing instance (expose it via a static/singleton accessor)
- Guard construction: keep a reference and skip re-instantiation if it already exists
- Dispose the previous instance and restart the process or refactor to allow re-init if a fresh manager is truly needed
Example fix
// before var manager = new WindowManager(dispatcher); // second call in process // after private static WindowManager manager; if (manager == null) manager = new WindowManager(dispatcher);
Defensive patterns
Strategy: try-catch
Validate before calling
if (WindowManager.Instance != null) useExisting(); else create();
Try / catch
try { manager = new WindowManager(dispatcher); } catch (InvalidOperationException ex) when (ex.Message.Contains("already existing")) { manager = WindowManager.Existing; } Prevention
- Use a singleton accessor
- Initialize once at app startup
- Never re-create during service restarts
When it happens
Trigger: Calling new WindowManager(dispatcher) twice in the same process, e.g. once at startup and again after re-initializing services or re-creating a ViewModel that owns one.
Common situations: Double application initialization (e.g. both App startup and a service locator warm-up); plugin or test harness constructing its own instance; forgetting Dispose does not reset initialized.
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 StrideAssetsViewModel class can be instanced only once.
- The SessionViewModel class can be instanced only once.
- A dependency object is already attached to this instance of…
- A dependency object must be attached in order to register a…
- A dependency object must be attached in order to unregister…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/f3e4ee589f45a7b2.
Report an issue: GitHub.
Appendix: source
Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Windows/WindowManager.cs:39
public class WindowManager : IDisposable
{
private static readonly List<WindowInfo> ModalWindowsList = new List<WindowInfo>();
private static readonly List<WindowInfo> BlockingWindowsList = new List<WindowInfo>();
private static readonly HashSet<WindowInfo> AllWindowsList = new HashSet<WindowInfo>();
// This must remains a field to prevent garbage collection!
private static NativeHelper.WinEventDelegate winEventProc;
private static IntPtr hook;
private static Dispatcher dispatcher;
private static bool initialized;
/// <summary>
/// Initializes a new instance of the <see cref="WindowManager"/> class.
/// </summary>
public WindowManager([NotNull] Dispatcher dispatcher)
{
if (dispatcher == null) throw new ArgumentNullException(nameof(dispatcher));
if (initialized) throw new InvalidOperationException("An instance of WindowManager is already existing.");
initialized = true;
winEventProc = WinEventProc;
WindowManager.dispatcher = dispatcher;
uint processId = (uint)Process.GetCurrentProcess().Id;
hook = NativeHelper.SetWinEventHook(NativeHelper.EVENT_OBJECT_SHOW, NativeHelper.EVENT_OBJECT_HIDE, IntPtr.Zero, winEventProc, processId, 0, NativeHelper.WINEVENT_OUTOFCONTEXT);
if (hook == IntPtr.Zero)
throw new InvalidOperationException("Unable to initialize the window manager.");
Logger.Info($"{nameof(WindowManager)} initialized");
}
#if DEBUG // Use a logger result for debugging
public static Logger Logger { get; } = new LoggerResult();
#else
public static Logger Logger { get; } = GlobalLogger.GetLogger(nameof(WindowManager));
#endif
View on GitHub (pinned to 96fad776d2)