SubtitleEdit/subtitleedit · error · InvalidOperationException

Failed to create window of type {typeof(T).Name} with constr

Error message

Failed to create window of type {typeof(T).Name} with constructor param {typeof(TViewModel).Name}

What it means

Thrown by WindowService.ShowWindow<T,TViewModel> when Activator.CreateInstance(typeof(T), viewModel) returns null after resolving the ViewModel from DI. For a reference-type Window this null return is effectively unreachable — Activator throws (MissingMethodException if no public ctor(TViewModel) exists, TargetInvocationException wrapping any exception the ctor raised) rather than returning null. So in practice you hit this guard only via the exception paths, but the guard's message names the intended diagnosis: the window could not be built from (TViewModel).

Source

Thrown at src/ui/Logic/WindowsService.cs:121

            window.Show();
            window.Focus();

            return window;
        }

        /// <inheritdoc />
        public TViewModel ShowWindow<T, TViewModel>(Window owner, Action<T, TViewModel>? configureViewModel = null)
            where T : Window
            where TViewModel : class
        {
            var viewModel = _serviceProvider.GetRequiredService<TViewModel>();

            // Create the window using reflection, passing in the viewModel
            var w = Activator.CreateInstance(typeof(T), viewModel);
            if (w == null)
            {
                throw new InvalidOperationException($"Failed to create window of type {typeof(T).Name} with constructor param {typeof(TViewModel).Name}");
            }

            var window = (T)w;
            configureViewModel?.Invoke(window, viewModel);

            window.WindowStartupLocation = WindowStartupLocation.CenterOwner;

            // Must run before Show() - see the note in ShowWindow<T>. (#12665)
            ApplyRightToLeftSettings(window);
            UiTheme.ApplyScaleToWindow(window);

            window.Show(owner);
            window.Focus();

            return viewModel;
        }

        /// <inheritdoc />

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Confirm window type T has a single public constructor whose parameter type is exactly TViewModel (the type registered in DI).
  2. Run the app under the debugger and inspect the inner exception of the TargetInvocationException thrown by Activator — that names the real missing service or null argument.
  3. Register TViewModel (and every service the window's constructor needs) in the service collection before calling ShowWindow.
  4. Verify the generic arguments at the call site are ordered <WindowType, ViewModelType> and not accidentally swapped.
  5. If a window legitimately needs extra ctor arguments, switch to the parameterless CreateWindow<T> path or add an overload rather than relying on the single-param Activator call.

Example fix

// before: window lacks the expected single-ViewModel constructor
public sealed class SettingsWindow : Window
{
    public SettingsWindow() { InitializeComponent(); } // no ViewModel param
}
var vm = windowService.ShowWindow<SettingsWindow, SettingsViewModel>(this);

// after: ctor takes exactly the ViewModel that DI resolved
public sealed class SettingsWindow : Window
{
    public SettingsWindow(SettingsViewModel vm) : this()
    {
        DataContext = vm;
    }
    private SettingsWindow() { InitializeComponent(); }
}
var vm = windowService.ShowWindow<SettingsWindow, SettingsViewModel>(this);
Defensive patterns

Strategy: validation

Validate before calling

// Verify the window has the constructor the Activator call needs before showing it.
using System.Reflection;

static bool HasViewModelCtor(Type window, Type vm)
{
    return window.GetConstructors().Any(c =>
        c.GetParameters() is { Length: 1 } p && p[0].ParameterType == vm);
}

if (!HasViewModelCtor(typeof(T), typeof(TViewModel)))
{
    throw new InvalidOperationException(
        $"{typeof(T).Name} must have a public ctor accepting {typeof(TViewModel).Name}.");
}
return windowService.ShowWindow<T, TViewModel>(owner, configureViewModel);

Try / catch

// The real failure arrives as an exception from Activator.CreateInstance,
// not the null guard — catch and unwrap the inner cause for the user.
try
{
    return windowService.ShowWindow<T, TViewModel>(owner, configureViewModel);
}
catch (TargetInvocationException ex) when (ex.InnerException != null)
{
    throw ex.InnerException; // surface the missing-service/null-arg from the window ctor
}
catch (MissingMethodException ex)
{
    throw new InvalidOperationException(
        $"{typeof(T).Name} has no public ctor({typeof(TViewModel).Name}).", ex);
}

Prevention

When it happens

Trigger: ShowWindow<T,TViewModel>(owner, configureViewModel) is called. The DI container resolves TViewModel (throws InvalidOperationException if unregistered — a different error). Then Activator.CreateInstance tries to invoke T's constructor taking a single TViewModel. Real failures surface as exceptions: MissingMethodException when T has no public constructor(TViewModel); TargetInvocationException when the constructor itself throws (e.g. its own DI dependency is missing). The literal null-check throw is the defensive tail.

Common situations: A new Window was added without a public constructor accepting its ViewModel; the constructor signature takes a different parameter type than the registered TViewModel; the Window's constructor calls a DI service that throws (service not registered, null argument); the Window and ViewModel types were swapped at the call site; refactor renamed/moved the ViewModel so the ctor param type no longer matches.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/19ed02308c20ba42. Report an issue: GitHub.