lepoco/wpfui · error · InvalidOperationException

{nameof(_serviceProvider.GetService)} returned null

Error message

{nameof(_serviceProvider.GetService)} returned null

What it means

Thrown by NavigationView.GetPageInstanceFromCache (the cache-fill path) when an IServiceProvider is configured but GetService(targetPageType) returns null. This is the cache-layer twin of error 35: same root cause (page not registered with DI) but surfaced while populating the navigation cache rather than during the primary resolution attempt. Note the message is shorter and lacks the type name, which can make diagnosis harder.

Source

Thrown at src/Wpf.Ui/Controls/NavigationView/NavigationView.Navigation.cs:317

        object? ComputeCachedNavigationInstance() => GetPageInstanceFromCache(viewItem.TargetPageType);
    }

    private object? GetPageInstanceFromCache(Type? targetPageType)
    {
        if (targetPageType is null)
        {
            return default;
        }

        if (_serviceProvider is not null)
        {
            System.Diagnostics.Debug.WriteLine(
                $"Getting {targetPageType} from cache using IServiceProvider."
            );

            return _serviceProvider.GetService(targetPageType)
                ?? throw new InvalidOperationException(
                    $"{nameof(_serviceProvider.GetService)} returned null"
                );
        }

        if (_pageService is not null)
        {
            System.Diagnostics.Debug.WriteLine(
                $"Getting {targetPageType} from cache using INavigationViewPageProvider."
            );

            return _pageService.GetPage(targetPageType)
                ?? throw new InvalidOperationException($"{nameof(_pageService.GetPage)} returned null");
        }

        System.Diagnostics.Debug.WriteLine($"Getting {targetPageType} from cache using reflection.");

        return NavigationViewActivator.CreateInstance(targetPageType)
            ?? throw new InvalidOperationException("Failed to create instance of the page");

View on GitHub (pinned to ffebacd610)

Solutions

  1. Register the page type with the IServiceProvider: services.AddTransient<MyPage>().
  2. Verify the registered type matches TargetPageType exactly.
  3. If using assembly scanning, ensure the page assembly is scanned.
  4. Alternatively disable caching for that item or supply a page provider.

Example fix

// before
builder.Services.AddSingleton<MainWindow>();
// MyPage missing -> throws on cached navigate

// after
builder.Services.AddTransient<MyPage>();
Defensive patterns

Strategy: validation

Validate before calling

if (_serviceProvider.GetService(targetPageType) is null)
    throw new InvalidOperationException(
        $"Page {targetPageType} not registered; cache cannot fill it.");

Type guard

static bool IsPageRegistered(IServiceProvider sp, Type t) => sp.GetService(t) is not null;

Prevention

When it happens

Trigger: Cache mode is active for a NavigationViewItem, GetNavigationItemInstance delegated to GetPageInstanceFromCache, an IServiceProvider is set, and GetService returns null for the target page type.

Common situations: Page type missing from DI while NavigationCacheMode is enabled (so the cache factory path runs); transient registration not registered; composition root conditionally omitted the page.

Related errors


AI-assisted analysis of lepoco/wpfui@ffebacd610 (2026-08-13). Data as JSON: /api/errors/ac7219774aa31529. Report an issue: GitHub.