dotnet/aspnetcore · error · InvalidOperationException
The type {NotFoundPage.FullName} does not have a Microsoft.A
Error message
The type {NotFoundPage.FullName} does not have a Microsoft.AspNetCore.Components.RouteAttribute applied to it. What it means
Thrown in Router.SetParametersAsync when NotFoundPage is set but the type has no [RouteAttribute] (i.e., no @page directive). The Router reads the type's [Route] attribute to derive the not-found route; without one it cannot route to it, so it rejects the configuration.
Source
Thrown at src/Components/Components/src/Routing/Router.cs:155
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)
{
_onNavigateCalled = true;
await RunOnNavigateAsync(NavigationManager.ToBaseRelativePath(_locationAbsolute), isNavigationIntercepted: false);
}
else
{
Refresh(isNavigationIntercepted: false);View on GitHub (pinned to 294cab2f9b)
Solutions
- Add a @page directive to the NotFoundPage component, e.g. @page "/404" (the exact path is not critical; the Router uses it as the route key).
- Confirm the [Route] attribute is present via NotFoundPage.GetCustomAttributes(typeof(RouteAttribute), inherit: true).
- Rebuild so the route attribute is emitted on the generated component class.
Example fix
<!-- before: NotFound.razor --> <h1>Not found</h1> <!-- after: NotFound.razor --> @page "/404" <h1>Not found</h1>
Defensive patterns
Strategy: validation
Validate before calling
static bool HasRouteAttribute(Type t) =>
t.GetCustomAttributes(typeof(RouteAttribute), inherit: true).Length > 0;
// Only bind NotFoundPage if it has a [Route]/@page.
<Router ... NotFoundPage="@(HasRouteAttribute(typeof(NotFound)) ? typeof(NotFound) : null)" /> Type guard
static bool IsRoutedComponent(Type t) =>
typeof(IComponent).IsAssignableFrom(t) &&
t.GetCustomAttributes(typeof(RouteAttribute), inherit: true).Length > 0; Prevention
- Always add an @page directive to the component passed to NotFoundPage.
- Add a test asserting NotFoundPage has a [Route] attribute.
- Rebuild after editing .razor so the route attribute is regenerated.
When it happens
Trigger: Setting NotFoundPage="@typeof(NotFound)" where NotFound.razor lacks an @page directive. The Router expects at least one [Route] on the type to use as its _notFoundPageRoute.
Common situations: Creating a dedicated 404 component but forgetting @page; an older sample where the 404 page had no route; refactoring that removed the @page line.
Related errors
- Setting NotFound and NotFoundPage properties simultaneously
- The Router component requires a value for the parameter AppA
- The Router component requires a value for the parameter Foun
- The type {NotFoundPage.FullName} does not implement Microsof
- The type {context.Handler.FullName} does not implement Micro
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/03916de243fb478e.
Report an issue: GitHub.