dotnet/aspnetcore · error · InvalidOperationException
The type does not implement .
Error message
The type {context.Handler.FullName} does not implement {typeof(IComponent).FullName}. What it means
At navigation time the Router resolves the location against its route table; if a handler matches but that handler type does not implement IComponent, the router throws InvalidOperationException before attempting to render. This is the runtime counterpart to the constructor-time RouteData check — it catches corruption introduced between table construction and navigation, e.g. by a route keying bug or a stray entry from a non-component assembly.
Solutions
- Audit the assemblies contributing routes; ensure only Blazor components are registered as handlers.
- Inspect the named type in the exception — if it is a controller or model, exclude that assembly from the Router's AdditionalAssemblies or filter the [Route] contributor.
- If you provide custom route entries, gate them on typeof(IComponent).IsAssignableFrom(handler).
- Clear route caches after a hot-reload that changes a type's base hierarchy.
Example fix
// before — custom route provider registers a non-component
entries.Add(new InboundRouteEntry { Handler = typeof(UserApi), ... });
// after
if (typeof(IComponent).IsAssignableFrom(typeof(UserPage)))
entries.Add(new InboundRouteEntry { Handler = typeof(UserPage), ... }); Defensive patterns
Strategy: type-guard
Validate before calling
// Guard custom route providers before adding entries.
if (!typeof(IComponent).IsAssignableFrom(context.Handler))
throw new InvalidOperationException($"{context.Handler} is not a component; refusing to register."); Type guard
static bool IsRouteHandler(Type t) => typeof(IComponent).IsAssignableFrom(t);
Prevention
- Filter all route-discovery scans by typeof(IComponent).IsAssignableFrom(t).
- Exclude MVC/controller assemblies from Router.AdditionalAssemblies.
- After hot-reload, clear route caches if a type's hierarchy changed.
- Add a startup test that loads the route table and asserts every handler is a component.
When it happens
Trigger: A route context whose Handler is set to a type that is not a component — typically because route discovery picked up an attribute on a non-component type, or because route table entries were mutated. Fires inside the navigation path after Routes.Route(context) resolves a handler.
Common situations: Custom route providers or IRouteDefinitionResolver implementations that emit entries for non-component types; assembly scanning that included MVC controllers or Razor Pages models decorated with a compatible attribute; a stale route table after hot-reload of a type into a non-component form.
Related errors
- The type does not implement .
- No component found for route
- Setting and properties simultaneously is not supported. Use…
- The component requires a value for the parameter .
- The component requires a value for the parameter .
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/5b2a659ef517de09.
Report an issue: GitHub.
Appendix: source
Thrown at src/Components/Components/src/Routing/Router.cs:265
_renderHandle.Render(Found(endpointRouteData));
if (ComponentsActivitySource.IsSupported && _renderHandle.ComponentActivitySource != null)
{
_renderHandle.ComponentActivitySource.StopNavigateActivity(activityHandle, null);
}
return;
}
RefreshRouteTable();
var context = new RouteContext(locationPath);
Routes.Route(context);
if (context.Handler != null)
{
if (!typeof(IComponent).IsAssignableFrom(context.Handler))
{
throw new InvalidOperationException($"The type {context.Handler.FullName} " +
$"does not implement {typeof(IComponent).FullName}.");
}
activityHandle = RecordDiagnostics(context.Handler.FullName, context.Entry.RoutePattern.RawText);
Log.NavigatingToComponent(_logger, context.Handler, locationPath, _baseUri);
var routeData = new RouteData(
context.Handler,
context.Parameters ?? _emptyParametersDictionary);
_renderHandle.Render(Found(routeData));
// If you navigate to a different path, then after the next render we'll update the scroll position
if (relativePath != _updateScrollPositionForHashLastLocation)
{
_updateScrollPositionForHashLastLocation = relativePath.ToString();
_updateScrollPositionForHash = true;View on GitHub (pinned to 3600ca084e)