tui-cs/Terminal.Gui · critical · InvalidOperationException
Cannot use modern instance-based model (Application.Create)
Error message
Cannot use modern instance-based model (Application.Create) after using legacy static Application model (Application.Init/ApplicationImpl.Instance). Use only one model per process.
What it means
Thrown inside Init when a non-singleton (instance-based) ApplicationImpl is being initialized but the process already used the legacy static model (the _instance singleton was initialized first). The error string is ERROR_MODERN_AFTER_LEGACY. It is the mirror of the ERROR_LEGACY_AFTER_MODERN check — the two models cannot coexist in one process because they share global driver and main-loop state.
Source
Thrown at Terminal.Gui/App/ApplicationImpl.Lifecycle.cs:54
// 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;
}
if (string.IsNullOrWhiteSpace (_driverName))
{
_driverName = ForceDriver;
}View on GitHub (pinned to 2e47b11478)
Solutions
- Standardize on the modern instance-based model and remove all Application.Init/Run/Shutdown calls.
- If you must keep legacy static, do not call Application.Create anywhere in the process.
- Run conflicting code in separate processes.
- In tests, reset the fence with ApplicationImpl.ResetModelUsageTracking() between incompatible cases.
Example fix
// before Application.Init (); // legacy static first // ... using var app = Application.Create ().Init (); // throws // after — modern model only using var app = Application.Create ().Init (); app.Run<MyWindow> ();
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the legacy static model was never used before calling Create. // Best practice: call Application.Create() first in Main, before any legacy API.
Prevention
- Call Application.Create() before any legacy static Application.* access.
- Remove all legacy Application.Init/Run/Shutdown calls when migrating.
- Keep conflicting code in separate processes.
When it happens
Trigger: Calling Application.Create().Init() after Application.Init() (legacy static) was already invoked; code that mixes Application.Init with Application.Create within the same process.
Common situations: Migrating an app piecemeal from legacy static to instance-based and leaving a stray Application.Init call; a library dependency that calls Application.Init while the host uses Create.
Related errors
- Cannot use legacy static Application model (Application.Init
- 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/92b649902f07c0a3.
Report an issue: GitHub.