{"record":{"id":"8bf7b2395098dbe6","repo":"dotnet/aspnetcore","slug":"invalid-layout-type-layouttype-fullname-does-no","errorCode":null,"errorMessage":"Invalid layout type: {layoutType.FullName} does not implement {typeof(IComponent).FullName}.","messagePattern":"Invalid layout type: (.+?) does not implement (.+?)\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/LayoutAttribute.cs","lineNumber":25,"sourceCode":"namespace Microsoft.AspNetCore.Components;\n\n/// <summary>\n/// Indicates that the associated component type uses a specified layout.\n/// </summary>\n[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]\npublic sealed class LayoutAttribute : Attribute\n{\n    /// <summary>\n    /// Constructs an instance of <see cref=\"LayoutAttribute\"/>.\n    /// </summary>\n    /// <param name=\"layoutType\">The type of the layout.</param>\n    public LayoutAttribute([DynamicallyAccessedMembers(Component)] Type layoutType)\n    {\n        LayoutType = layoutType ?? throw new ArgumentNullException(nameof(layoutType));\n\n        if (!typeof(IComponent).IsAssignableFrom(layoutType))\n        {\n            throw new ArgumentException($\"Invalid layout type: {layoutType.FullName} \" +\n                $\"does not implement {typeof(IComponent).FullName}.\");\n        }\n\n        // Note that we can't validate its acceptance of a 'Body' parameter at this stage,\n        // because the contract doesn't force them to be known statically. However it will\n        // be a runtime error if the referenced component type rejects the 'Body' parameter\n        // when it gets used.\n    }\n\n    /// <summary>\n    /// The type of the layout. The type must implement <see cref=\"IComponent\"/>\n    /// and must accept a parameter with the name 'Body'.\n    /// </summary>\n    [DynamicallyAccessedMembers(Component)]\n    public Type LayoutType { get; private set; }\n}\n","sourceCodeStart":7,"sourceCodeEnd":42,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Components/src/LayoutAttribute.cs#L7-L42","documentation":"The type passed to LayoutAttribute must implement IComponent, because a layout is itself a Blazor component that renders a Body fragment. Passing a plain class, interface, or record is rejected with ArgumentException.","triggerScenarios":"[Layout(typeof(NonComponentClass))] where NonComponentClass does not implement IComponent.","commonSituations":"Pointing LayoutAttribute at a plain C# class, a stale type reference after renaming, or a type that is data-only rather than a Razor component.","solutions":["Make the layout a Razor component (it inherits ComponentBase, which implements IComponent).","Verify the type reference resolves to the intended layout component.","Use @layout directive or [Layout(typeof(MyLayout))] with a real component type."],"exampleFix":"// before\n[Layout(typeof(SomePlainClass))]\n// after\n[Layout(typeof(MyLayout))]  // MyLayout.razor : ComponentBase","handlingStrategy":"type-guard","validationCode":"if (!typeof(IComponent).IsAssignableFrom(layoutType))\n    throw new ArgumentException($\"{layoutType} must implement IComponent.\");","typeGuard":"static bool IsValidLayout(Type t) => typeof(IComponent).IsAssignableFrom(t);","tryCatchPattern":null,"preventionTips":["Use Razor component types (which inherit ComponentBase) as layouts.","Validate typeof(IComponent).IsAssignableFrom before applying LayoutAttribute.","Keep layout types in a known set of components."],"tags":["blazor","layout","type-validation","attribute"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}