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

  1. Standardize on the modern instance-based model and remove all Application.Init/Run/Shutdown calls.
  2. If you must keep legacy static, do not call Application.Create anywhere in the process.
  3. Run conflicting code in separate processes.
  4. 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

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


AI-assisted analysis of tui-cs/Terminal.Gui@2e47b11478 (2026-08-13). Data as JSON: /api/errors/92b649902f07c0a3. Report an issue: GitHub.