dotnet/aspnetcore · error · ArgumentException

The type {componentType.FullName} does not implement {nameof

Error message

The type {componentType.FullName} does not implement {nameof(IComponent)}.

What it means

Thrown by DefaultComponentActivator.CreateInstance when the requested type does not implement IComponent. Blazor's component instantiation requires the type to be a valid component; passing a plain class, struct, or non-component type is an error. The check is at DefaultComponentActivator.cs:28-31.

Source

Thrown at src/Components/Components/src/DefaultComponentActivator.cs:30

{
    private static readonly ConcurrentDictionary<Type, ObjectFactory> _cachedComponentTypeInfo = new();

    static DefaultComponentActivator()
    {
        if (HotReloadManager.IsSupported)
        {
            HotReloadManager.Default.OnDeltaApplied += ClearCache;
        }
    }

    public static void ClearCache() => _cachedComponentTypeInfo.Clear();

    /// <inheritdoc />
    public IComponent CreateInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type componentType)
    {
        if (!typeof(IComponent).IsAssignableFrom(componentType))
        {
            throw new ArgumentException($"The type {componentType.FullName} does not implement {nameof(IComponent)}.", nameof(componentType));
        }

        var factory = GetObjectFactory(componentType);

        return (IComponent)factory(serviceProvider, []);
    }

    private static ObjectFactory GetObjectFactory([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type componentType)
    {
        // Unfortunately we can't use 'GetOrAdd' here because the DynamicallyAccessedMembers annotation doesn't flow through to the
        // callback, so it becomes an IL2111 warning. The following is equivalent and thread-safe because it's a ConcurrentDictionary
        // and it doesn't matter if we build a cache entry more than once.
        if (!_cachedComponentTypeInfo.TryGetValue(componentType, out var factory))
        {
            factory = ActivatorUtilities.CreateFactory(componentType, Type.EmptyTypes);
            _cachedComponentTypeInfo.TryAdd(componentType, factory);
        }

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Ensure the type derives from ComponentBase (or implements IComponent directly).
  2. Verify the Type passed to DynamicComponent is actually a Razor component, not a data model.
  3. If loading types dynamically, filter candidates to those implementing IComponent.

Example fix

// before
public class MyData { public int Id; } // not a component

<DynamicComponent Type="@typeof(MyData)" />

// after
public class MyDataComponent : ComponentBase
{
    [Parameter] public int Id { get; set; }
}

<DynamicComponent Type="@typeof(MyDataComponent)" />
Defensive patterns

Strategy: type-guard

Validate before calling

if (!typeof(IComponent).IsAssignableFrom(componentType))
    throw new ArgumentException($"{componentType} does not implement IComponent.");

Type guard

static bool IsValidComponentType(Type t) => typeof(IComponent).IsAssignableFrom(t);

Prevention

When it happens

Trigger: Passing a type to DynamicComponent's Type parameter, a custom activator, or a root component registration where the type does not implement IComponent (i.e., does not derive from ComponentBase or implement the interface directly).

Common situations: Passing a POCO or service class to DynamicComponent Type; wiring up a type by name that is a model not a component; reflection-based component loading that picks the wrong type.

Related errors


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