dotnet/aspnetcore · error · InvalidOperationException

Setting NotFound and NotFoundPage properties simultaneously

Error message

Setting NotFound and NotFoundPage properties simultaneously is not supported. Use either NotFound or NotFoundPage.

What it means

Thrown in Router.SetParametersAsync when both NotFound (the deprecated RenderFragment) and NotFoundPage (the newer Type-based property) are set. They are two ways to specify 404 content and the Router cannot honor both, so simultaneous use is rejected to avoid ambiguous behavior.

Source

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

        if (AppAssembly == null)
        {
            throw new InvalidOperationException($"The {nameof(Router)} component requires a value for the parameter {nameof(AppAssembly)}.");
        }

        // 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)
            {

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Choose one API: keep NotFoundPage and delete the <NotFound> template, or remove NotFoundPage and keep <NotFound>.
  2. Prefer NotFoundPage (NotFound is [Obsolete]) for new code.
  3. Rebuild after removing one to confirm the error clears.

Example fix

<!-- before -->
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="@typeof(NotFound)">
    <NotFound><p>Not found</p></NotFound>
</Router>

<!-- after -->
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="@typeof(NotFound)">
</Router>
Defensive patterns

Strategy: validation

Validate before calling

// Set exactly one of NotFound or NotFoundPage. Prefer NotFoundPage for new code.
@if (UseNotFoundPage) {
    <Router AppAssembly="@typeof(Program).Assembly" Found="@Found" NotFoundPage="@typeof(NotFound)" />
} else {
    <Router AppAssembly="@typeof(Program).Assembly" Found="@Found">
        <NotFound><p>Not found</p></NotFound>
    </Router>
}

Prevention

When it happens

Trigger: A <Router> that declares both <NotFound>...</NotFound> and NotFoundPage="@typeof(MyNotFound)". Migrating from the old NotFound API to NotFoundPage and leaving the old block in place.

Common situations: Following an upgrade/migration guide that recommends NotFoundPage but forgetting to remove the existing <NotFound> template; copy-paste between sample projects that use different APIs.

Related errors


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