{"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":"critical","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/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Components/src/LayoutAttribute.cs#L7-L42","documentation":"Thrown by the LayoutAttribute constructor when the type passed as the layout does not implement IComponent. Blazor requires every layout to be a renderable component, so the attribute validates this contract at construction time. The check uses typeof(IComponent).IsAssignableFrom(layoutType), so any non-component type (e.g. a plain class or interface) triggers it.","triggerScenarios":"Decorating a class with [Layout(typeof(SomeNonComponentType))] where SomeNonComponentType does not implement IComponent; passing a Type instance to LayoutAttribute whose hierarchy does not include IComponent; referencing a layout type that was refactored away from inheriting ComponentBase/IComponent.","commonSituations":"Creating a custom layout that mistakenly inherits from a non-component base class; copy-pasting a layout reference and forgetting to inherit ComponentBase; Razor @layout directive resolving to a helper/utility class rather than a component; trimming/AOT scenarios where the type metadata is incomplete.","solutions":["Make the referenced layout type implement IComponent, typically by inheriting from LayoutComponentBase or ComponentBase.","Verify the type passed to [Layout(...)] is the component you intend (check the using/namespace resolution).","Add a [Body] RenderFragment parameter to the layout so it functions as a real layout."],"exampleFix":"// before\n[Layout(typeof(MainLayoutShell))] // MainLayoutShell : UserControl, not a component\npublic class MyPage : ComponentBase { }\n\n// after\n[Layout(typeof(MainLayout))]   // MainLayout : LayoutComponentBase\npublic class MyPage : ComponentBase { }","handlingStrategy":"validation","validationCode":"static bool IsValidLayout(Type t) => t != null && typeof(IComponent).IsAssignableFrom(t);\n\n// before decorating or resolving:\nif (!IsValidLayout(candidateLayoutType)) throw new InvalidOperationException($\"{candidateLayoutType} is not a valid layout component.\");","typeGuard":"static bool IsLayoutComponent(Type t) => typeof(IComponent).IsAssignableFrom(t);","tryCatchPattern":"try { var attr = new LayoutAttribute(layoutType); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"does not implement\"))\n{\n    logger.LogError(ex, \"Layout type invalid\");\n    throw;\n}","preventionTips":["Always derive layouts from LayoutComponentBase.","Add a unit test asserting [Layout]-referenced types implement IComponent.","Use nameof/typed references instead of typeof(string) lookups for layouts."],"tags":["blazor","layout","component","configuration","type-validation"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}