{"record":{"id":"59bc3435d56b85cf","repo":"tui-cs/Terminal.Gui","slug":"the-runnable-is-already-running","errorCode":null,"errorMessage":"The runnable is already running.","messagePattern":"The runnable is already running\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Terminal.Gui/App/ApplicationImpl.Run.cs","lineNumber":118,"sourceCode":"                         {\n                             action.Invoke ();\n\n                             return false;\n                         });\n    }\n\n    #endregion Timeouts and Invoke\n\n    #region Session Lifecycle - Begin\n\n    /// <inheritdoc/>\n    public SessionToken? Begin (IRunnable runnable)\n    {\n        ArgumentNullException.ThrowIfNull (runnable);\n\n        if (runnable.IsRunning)\n        {\n            throw new ArgumentException (@\"The runnable is already running.\", nameof (runnable));\n        }\n\n        // Create session token\n        SessionToken token = new (runnable);\n\n        Trace.Lifecycle (MainThreadId.ToString (), \"Begin\", \"(token.Runnable as Runnable)?.ToIdentifyingString ()\");\n\n        // Get old IsRunning value BEFORE any stack changes (safe - cached value)\n        bool oldIsRunning = runnable.IsRunning;\n\n        // Raise IsRunningChanging OUTSIDE lock (false -> true) - can be canceled\n        if (runnable.RaiseIsRunningChanging (oldIsRunning, true))\n        {\n            // Starting was canceled\n            return null;\n        }\n\n        // Set the application reference in the runnable","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/tui-cs/Terminal.Gui/blob/2e47b11478db083499917f2ad27c34d30efb0df1/Terminal.Gui/App/ApplicationImpl.Run.cs#L100-L136","documentation":"Thrown by ApplicationImpl.Begin(IRunnable) when runnable.IsRunning is already true. Begin is the low-level session-start API; it refuses to start a runnable that is already on the session stack. The higher-level Run API guards against this by reusing an existing token, so this exception surfaces when Begin is called directly on an active runnable.","triggerScenarios":"Calling app.Begin(runnable) on a runnable already returned by a prior Begin/Run that has not been Ended; manually calling Begin instead of Run and losing track of the session; nesting the same dialog without ending it first.","commonSituations":"Custom navigation logic that re-opens a modal Window/Dialog that is still running; event handlers that call Begin twice on the same object; misuse of the low-level Begin API when Run would have been correct.","solutions":["Check runnable.IsRunning before calling Begin, and End the existing session first if you need to restart it.","Prefer the higher-level Run/Run<T> API which already handles re-entrant runnables by reusing the existing token.","Track the SessionToken returned by Begin and ensure End(token) is called before re-beginning."],"exampleFix":"// before\napp.Begin (runnable);\n// ...\napp.Begin (runnable); // throws — still running\n\n// after\nif (!runnable.IsRunning)\n{\n    app.Begin (runnable);\n}","handlingStrategy":"validation","validationCode":"if (!runnable.IsRunning)\n{\n    app.Begin (runnable);\n}","typeGuard":"static bool CanBegin (IRunnable r) => !r.IsRunning;","tryCatchPattern":null,"preventionTips":["Check runnable.IsRunning before calling Begin.","Prefer Run/Run<T> which handle re-entrant runnables safely.","Track and End SessionTokens before re-beginning a runnable."],"tags":["session","runnable","lifecycle"],"backgroundTag":null,"analyzedSha":"2e47b11478db083499917f2ad27c34d30efb0df1","analyzedAt":"2026-08-13T19:20:08.826Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}