stride3d/stride · error · InvalidOperationException
This controller is beeing disposed.
Error message
This controller is beeing disposed.
What it means
EditorGameController.StartGame refuses to run when the controller is in the process of being destroyed (IsDestroying is true). Starting a game thread while teardown is in progress would create new game-side resources that no one will clean up, so it throws InvalidOperationException instead of EnsureNotDestroyed's ObjectDisposedException.
Solutions
- Check controller.IsDestroying / IsDestroyed before calling StartGame and skip the call.
- Await the editor's close/dispose completion before issuing a new StartGame for a replacement controller.
- Cancel pending StartGame work when the asset editor is closing (tie it to the asset lifecycle).
Example fix
// before
await controller.StartGame();
// after
if (!controller.IsDestroyed && !controller.IsDestroying)
await controller.StartGame(); Defensive patterns
Strategy: validation
Validate before calling
if (controller.IsDestroyed || controller.IsDestroying)
return false; // skip StartGame during teardown Type guard
bool IsUsable(EditorGameControllerBase c) => !c.IsDestroyed && !c.IsDestroying;
Try / catch
try { await controller.StartGame(); }
catch (InvalidOperationException) { /* controller being disposed; abandon start */ } Prevention
- Cancel deferred start tasks when the asset editor closes
- Recreate a fresh controller instead of restarting a disposing one
- Tie controller usage to the asset editor lifetime
When it happens
Trigger: Calling StartGame() after Destroy() has begun (IsDestroying == true) but possibly before it fully completes — e.g. a fast asset close/reopen cycle, or an async task that was awaiting something and resumes StartGame after the editor closed the asset.
Common situations: Editor session or asset closing while a deferred start request is still pending; user closes the asset editor tab while game preview startup is in flight; race between dispose and initialization code.
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
- This controller has already been disposed.
- this
- EffectSystem has been disposed. This Effect compilation has…
- Trying to dispose a lock that has already been released.
- The default profile cannot be unloaded
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/2688da7549e7c9b5.
Report an issue: GitHub.
Appendix: source
Thrown at sources/editor/Stride.Assets.Presentation/AssetEditors/GameEditor/Services/EditorGameController.cs:230
[CanBeNull]
protected abstract object FindPart(AbsoluteId partId);
public T GetService<T>() where T : IEditorGameViewModelService
{
EnsureNotDestroyed();
EnsureAssetAccess();
if (IsDestroying || serviceRegistry == null)
return default(T);
return serviceRegistry.Get<T>();
}
/// <inheritdoc/>
public async Task<bool> StartGame()
{
EnsureNotDestroyed();
if (IsDestroying)
throw new InvalidOperationException("This controller is beeing disposed.");
// Run the game in a separate thread (create Form and run)
sceneGameThread.Start();
// Wait for the game to start
await gameStartedTaskSource.Task;
GameForm.MouseDown += (sender, e) => lastClickPosition = Control.MousePosition;
// Initialize the WPF GameEngineHwndHost on this thread
GameForm.Host = new GameEngineHost(windowHandle);
// TODO: we could check if the game fails to create.
return true;
}
public void OnHideGame()
{
Game.IsEditorHidden = true;
}
public void OnShowGame()View on GitHub (pinned to 96fad776d2)