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

  1. Ensure the type passed to OpenComponent inherits from ComponentBase or directly implements IComponent.
  2. If using reflection to resolve component types, add a type check: if (!typeof(IComponent).IsAssignableFrom(type)) return; before calling OpenComponent.
  3. Use the generic overload OpenComponent<TComponent>() where TComponent : IComponent for compile-time safety.
  4. 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

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


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