dotnet/aspnetcore · error · InvalidOperationException

The type {NotFoundPage.FullName} does not implement Microsof

Error message

The type {NotFoundPage.FullName} does not implement Microsoft.AspNetCore.Components.IComponent.

What it means

Thrown in Router.SetParametersAsync when NotFoundPage is set to a type that does not implement IComponent. The Router renders NotFoundPage as a routed page component (it looks up its [Route] template and renders it), so it must be a real Blazor component, not an arbitrary type.

Source

Thrown at src/Components/Components/src/Routing/Router.cs:148

        // Found content is mandatory, because even though we could use something like <RouteView ...> as a
        // reasonable default, if it's not declared explicitly in the template then people will have no way
        // to discover how to customize this (e.g., to add authorization).
        if (Found == null)
        {
            throw new InvalidOperationException($"The {nameof(Router)} component requires a value for the parameter {nameof(Found)}.");
        }

        if (NotFoundPage != null)
        {
#pragma warning disable CS0618 // Type or member is obsolete
            if (NotFound != null)
            {
                throw new InvalidOperationException($"Setting {nameof(NotFound)} and {nameof(NotFoundPage)} properties simultaneously is not supported. Use either {nameof(NotFound)} or {nameof(NotFoundPage)}.");
            }
#pragma warning restore CS0618 // Type or member is obsolete
            if (!typeof(IComponent).IsAssignableFrom(NotFoundPage))
            {
                throw new InvalidOperationException($"The type {NotFoundPage.FullName} " +
                    $"does not implement {typeof(IComponent).FullName}.");
            }

            var routeAttributes = NotFoundPage.GetCustomAttributes(typeof(RouteAttribute), inherit: true);
            if (routeAttributes.Length == 0)
            {
                throw new InvalidOperationException($"The type {NotFoundPage.FullName} " +
                    $"does not have a {typeof(RouteAttribute).FullName} applied to it.");
            }

            var routeAttribute = (RouteAttribute)routeAttributes[0];
            if (routeAttribute.Template != null)
            {
                _notFoundPageRoute = routeAttribute.Template;
            }
        }

        if (!_onNavigateCalled)

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Ensure the type passed to NotFoundPage is a Blazor component (a .razor file with @page, which derives from ComponentBase).
  2. Verify typeof(IComponent).IsAssignableFrom(NotFoundPage) at the call site or in a test.
  3. If the type is meant to be the 404 page, make it a component with @page "/404" (or similar).

Example fix

<!-- before -->
<Router ... NotFoundPage="@typeof(NotFoundModel)" /> <!-- NotFoundModel is not a component -->

<!-- after -->
<!-- NotFound.razor: @page "/404" -->
<Router ... NotFoundPage="@typeof(NotFound)" />
Defensive patterns

Strategy: type-guard

Validate before calling

static Type? ResolveNotFoundPage(Type candidate)
    => candidate is not null && typeof(IComponent).IsAssignableFrom(candidate) ? candidate : null;

Type guard

static bool IsComponentType(Type t) => typeof(IComponent).IsAssignableFrom(t);

Prevention

When it happens

Trigger: Setting NotFoundPage="@typeof(SomeClass)" where SomeClass does not implement IComponent (e.g., a plain page model, a static HTML helper, or a Razor class that is not a component).

Common situations: Pointing NotFoundPage at a layout type or a non-component Razor file; a refactor where the 404 page lost its @inherits ComponentBase; confusion between a component and a plain Razor view.

Related errors


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/d78d488603f2f2ef. Report an issue: GitHub.