tui-cs/Terminal.Gui · critical · InvalidOperationException
Cannot use legacy static Application model (Application.Init
Error message
Cannot use legacy static Application model (Application.Init/ApplicationImpl.Instance) after using modern instance-based model (Application.Create). Use only one model per process.
What it means
Thrown inside Init when the legacy static Application singleton (_instance) is being initialized but the process already used the modern instance-based model (Application.Create). Terminal.Gui v2 forbids mixing the two models because they share global driver/main-loop state; using both would corrupt the synchronization context and driver ownership. The error string is ERROR_LEGACY_AFTER_MODERN.
Source
Thrown at Terminal.Gui/App/ApplicationImpl.Lifecycle.cs:48
}
MainThreadId = Thread.CurrentThread.ManagedThreadId;
Trace.Lifecycle (MainThreadId?.ToString (), "Init", $"driverName: {driverName}");
// In Application.Init(), before starting the input thread:
// Pre-warm the Wcwidth static cache to prevent ZeroTable._lookup race condition
// See: https://github.com/spectreconsole/wcwidth/issues/11
_ = UnicodeCalculator.GetWidth (new Rune ('A'));
// Thread-safe fence check: Ensure we're not mixing application models
// Use lock to make check-and-set atomic
lock (_modelUsageLock)
{
// If this is a legacy static instance and instance-based model was used, throw
if (this == _instance && ModelUsage == ApplicationModelUsage.InstanceBased)
{
throw new InvalidOperationException (ERROR_LEGACY_AFTER_MODERN);
}
// If this is an instance-based instance and legacy static model was used, throw
if (this != _instance && ModelUsage == ApplicationModelUsage.LegacyStatic)
{
throw new InvalidOperationException (ERROR_MODERN_AFTER_LEGACY);
}
// If no model has been set yet, set it now based on which instance this is
if (ModelUsage == ApplicationModelUsage.None)
{
ModelUsage = this == _instance ? ApplicationModelUsage.LegacyStatic : ApplicationModelUsage.InstanceBased;
}
}
if (!string.IsNullOrWhiteSpace (driverName))
{
_driverName = driverName;View on GitHub (pinned to 2e47b11478)
Solutions
- Pick one model per process and use it consistently: prefer the modern instance-based model (Application.Create).
- If a dependency forces the legacy model, run your app with the legacy static API (Application.Init/Run/Shutdown) throughout.
- Isolate conflicting code into a subprocess so each process uses only one model.
- Call ApplicationImpl.ResetModelUsageTracking() (test-only) only in controlled test scenarios to reset the fence.
Example fix
// before using var app = Application.Create ().Init (); // ... later ... Application.Init (); // legacy static after modern — throws // after — use only the modern model using var app = Application.Create ().Init (); app.Run<MyWindow> ();
Defensive patterns
Strategy: validation
Validate before calling
// Pick one model at process start and never mix. // Modern (recommended): using var app = Application.Create ().Init (); // Do NOT call Application.Init() anywhere after this.
Prevention
- Standardize the entire process on one application model.
- Audit third-party libraries for Application.Init / Application.* static calls before integrating.
- Prefer the modern instance-based model (Application.Create) for new code.
When it happens
Trigger: Calling Application.Init() (legacy static facade) after Application.Create() was already invoked elsewhere in the same process; a third-party library or test helper that uses the legacy static API while the host app uses the modern instance-based API.
Common situations: Integrating a library written against the v1/legacy static API into a v2 app that uses Application.Create(); mixing UICatalog-style instance code with legacy snippets; a dependency that internally calls Application.Init.
Related errors
- Cannot use modern instance-based model (Application.Create)
- Cannot use legacy static Application model (Application.Init
- Cannot use modern instance-based model (Application.Create)
- Init called multiple times without Shutdown
- DefaultKeyBindings dictionary is null. Initialize it before
AI-assisted analysis of tui-cs/Terminal.Gui@2e47b11478 (2026-08-13).
Data as JSON: /api/errors/187cd46740009715.
Report an issue: GitHub.