{"record":{"id":"2688da7549e7c9b5","repo":"stride3d/stride","slug":"this-controller-is-beeing-disposed","errorCode":null,"errorMessage":"This controller is beeing disposed.","messagePattern":"This controller is beeing disposed\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/editor/Stride.Assets.Presentation/AssetEditors/GameEditor/Services/EditorGameController.cs","lineNumber":230,"sourceCode":"\n        [CanBeNull]\n        protected abstract object FindPart(AbsoluteId partId);\n\n        public T GetService<T>() where T : IEditorGameViewModelService\n        {\n            EnsureNotDestroyed();\n            EnsureAssetAccess();\n            if (IsDestroying || serviceRegistry == null)\n                return default(T);\n            return serviceRegistry.Get<T>();\n        }\n\n        /// <inheritdoc/>\n        public async Task<bool> StartGame()\n        {\n            EnsureNotDestroyed();\n            if (IsDestroying)\n                throw new InvalidOperationException(\"This controller is beeing disposed.\");\n            // Run the game in a separate thread (create Form and run)\n            sceneGameThread.Start();\n            // Wait for the game to start\n            await gameStartedTaskSource.Task;\n            GameForm.MouseDown += (sender, e) => lastClickPosition = Control.MousePosition;\n            // Initialize the WPF GameEngineHwndHost on this thread\n            GameForm.Host = new GameEngineHost(windowHandle);\n\n            // TODO: we could check if the game fails to create.\n            return true;\n        }\n\n        public void OnHideGame()\n        {\n            Game.IsEditorHidden = true;\n        }\n\n        public void OnShowGame()","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/editor/Stride.Assets.Presentation/AssetEditors/GameEditor/Services/EditorGameController.cs#L212-L248","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nawait controller.StartGame();\n// after\nif (!controller.IsDestroyed && !controller.IsDestroying)\n    await controller.StartGame();","handlingStrategy":"validation","validationCode":"if (controller.IsDestroyed || controller.IsDestroying)\n    return false; // skip StartGame during teardown","typeGuard":"bool IsUsable(EditorGameControllerBase c) => !c.IsDestroyed && !c.IsDestroying;","tryCatchPattern":"try { await controller.StartGame(); }\ncatch (InvalidOperationException) { /* controller being disposed; abandon start */ }","preventionTips":["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"],"tags":["disposed","lifecycle","race-condition","game-editor"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}