dotnet/aspnetcore · error · ArgumentException
The component type must implement Microsoft.AspNetCore.Compo
Error message
The component type must implement Microsoft.AspNetCore.Components.IComponent.
What it means
RenderTreeBuilder.OpenComponent(int, Type) validates that the provided type implements IComponent before proceeding. Blazor components must implement IComponent (typically by inheriting ComponentBase). If a non-IComponent type is passed, it throws ArgumentException. This is a type-safety guard preventing the renderer from attempting to render an arbitrary class as a component.
Source
Thrown at src/Components/Components/src/Rendering/RenderTreeBuilder.cs:506
/// <summary>
/// Appends a frame representing a child component.
/// </summary>
/// <typeparam name="TComponent">The type of the child component.</typeparam>
/// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
public void OpenComponent<[DynamicallyAccessedMembers(Component)] TComponent>(int sequence) where TComponent : notnull, IComponent
=> OpenComponentUnchecked(sequence, typeof(TComponent));
/// <summary>
/// Appends a frame representing a child component.
/// </summary>
/// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
/// <param name="componentType">The type of the child component.</param>
public void OpenComponent(int sequence, [DynamicallyAccessedMembers(Component)] Type componentType)
{
if (!typeof(IComponent).IsAssignableFrom(componentType))
{
throw new ArgumentException($"The component type must implement {typeof(IComponent).FullName}.");
}
OpenComponentUnchecked(sequence, componentType);
}
/// <summary>
/// Appends a frame representing a component parameter.
/// </summary>
/// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
/// <param name="name">The name of the attribute.</param>
/// <param name="value">The value of the attribute.</param>
public void AddComponentParameter(int sequence, string name, object? value)
{
AssertCanAddComponentParameter();
_entries.AppendAttribute(sequence, name, value);
}
/// <summary>View on GitHub (pinned to 294cab2f9b)
Solutions
- Ensure the type passed to OpenComponent inherits from ComponentBase or directly implements IComponent.
- If using reflection to resolve component types, add a type check: if (!typeof(IComponent).IsAssignableFrom(type)) return; before calling OpenComponent.
- Use the generic overload OpenComponent<TComponent>() where TComponent : IComponent for compile-time safety.
- Verify that the type argument is the component class (typically in a .razor or ComponentBase-derived class), not a data model.
Example fix
// before var type = typeof(UserViewModel); // not a component builder.OpenComponent(0, type); // throws // after var type = typeof(UserProfileComponent); // implements IComponent builder.OpenComponent(0, type);
Defensive patterns
Strategy: validation
Validate before calling
// Validate type implements IComponent before opening
static void SafeOpenComponent(RenderTreeBuilder builder, int seq, Type componentType)
{
if (!typeof(IComponent).IsAssignableFrom(componentType))
throw new ArgumentException(
$"{componentType.FullName} does not implement IComponent");
builder.OpenComponent(seq, componentType);
} Type guard
// Prefer the generic overload for compile-time safety builder.OpenComponent<MyComponent>(0); // TComponent : IComponent enforced by constraint
Prevention
- Prefer the generic OpenComponent<TComponent>() overload for compile-time type safety.
- When using reflection to resolve types, validate typeof(IComponent).IsAssignableFrom(type) first.
- Maintain a registry of known component types to avoid passing wrong types dynamically.
- Unit test dynamic component rendering with both valid and invalid types.
When it happens
Trigger: Calling builder.OpenComponent(0, typeof(MyPlainClass)) where MyPlainClass does not implement IComponent. This can happen in dynamically-typed rendering scenarios, reflection-based component registration, or when passing a view-model or DTO type instead of a component type.
Common situations: Passing a non-component type via reflection or dynamic type resolution; confusion between a data model class and its corresponding component; generic code that accepts arbitrary types and tries to render them as components; passing a typeof(SomeService) instead of typeof(SomeComponent).
Related errors
- Invalid layout type: {layoutType.FullName} does not implemen
- Services cannot be accessed before the component is initiali
- The type '{targetType.FullName}' declares more than one para
- The event handler parameter type {declaredType.FullName} for
- More than one sibling of component '{frame.ComponentTypeFiel
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/7b0b38694417be8a.
Report an issue: GitHub.