{"record":{"id":"ddedee455b4fe5c4","repo":"dotnet/aspnetcore","slug":"the-frametype-must-be-attribute","errorCode":null,"errorMessage":"The FrameType must be Attribute.","messagePattern":"The FrameType must be Attribute\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/Rendering/RenderTreeBuilder.cs","lineNumber":428,"sourceCode":"            AssertCanAddAttribute();\n        }\n    }\n\n    /// <summary>\n    /// <para>\n    /// Appends a frame representing an attribute.\n    /// </para>\n    /// <para>\n    /// The attribute is associated with the most recently added element.\n    /// </para>\n    /// </summary>\n    /// <param name=\"sequence\">An integer that represents the position of the instruction in the source code.</param>\n    /// <param name=\"frame\">A <see cref=\"RenderTreeFrame\"/> holding the name and value of the attribute.</param>\n    public void AddAttribute(int sequence, RenderTreeFrame frame)\n    {\n        if (frame.FrameTypeField != RenderTreeFrameType.Attribute)\n        {\n            throw new ArgumentException($\"The {nameof(frame.FrameType)} must be {RenderTreeFrameType.Attribute}.\");\n        }\n\n        AssertCanAddAttribute();\n        frame.SequenceField = sequence;\n        _entries.Append(frame);\n    }\n\n    /// <summary>\n    /// Adds frames representing multiple attributes with the same sequence number.\n    /// </summary>\n    /// <param name=\"sequence\">An integer that represents the position of the instruction in the source code.</param>\n    /// <param name=\"attributes\">A collection of key-value pairs representing attributes.</param>\n    public void AddMultipleAttributes(int sequence, IEnumerable<KeyValuePair<string, object>>? attributes)\n    {\n        // Calling this up-front just to make sure we validate before mutating anything.\n        AssertCanAddAttribute();\n\n        if (attributes != null)","sourceCodeStart":410,"sourceCodeEnd":446,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Components/src/Rendering/RenderTreeBuilder.cs#L410-L446","documentation":"RenderTreeBuilder.AddAttribute(int, RenderTreeFrame) accepts a pre-built RenderTreeFrame and appends it as an attribute. It validates that the frame's FrameType is Attribute; otherwise it throws ArgumentException. This prevents appending a frame of the wrong type (Element, Component, Text, etc.) through the attribute-adding API.","triggerScenarios":"Calling builder.AddAttribute(sequence, frame) where frame was constructed as a non-Attribute frame type. This is an internal/low-level API misuse, typically in code that builds RenderTreeFrame instances manually via the internal factory methods or reflection.","commonSituations":"Custom rendering extension code that constructs RenderTreeFrame instances; test code that manually creates frames; framework-level code that reuses frame objects incorrectly.","solutions":["Ensure any RenderTreeFrame passed to AddAttribute(int, RenderTreeFrame) has FrameType == RenderTreeFrameType.Attribute.","Use the typed overloads AddAttribute(int, string, T) for normal attribute addition instead of the frame-based overload.","If working with raw frames, verify frame.FrameType before calling AddAttribute.","Construct attribute frames using the internal RenderTreeFrame attribute factory methods only."],"exampleFix":"// before\nvar frame = RenderTreeFrame.Element(0, \"div\", 1); // Element frame\nbuilder.AddAttribute(0, frame); // throws: not Attribute\n\n// after\nbuilder.AddAttribute(0, \"class\", \"my-class\"); // use typed overload","handlingStrategy":"validation","validationCode":"// Validate frame type before calling AddAttribute(int, RenderTreeFrame)\nstatic void SafeAddAttributeFrame(RenderTreeBuilder builder, int seq, RenderTreeFrame frame)\n{\n    if (frame.FrameType != RenderTreeFrameType.Attribute)\n        throw new ArgumentException($\"Frame must be Attribute, got {frame.FrameType}\");\n    builder.AddAttribute(seq, frame);\n}","typeGuard":"static bool IsAttributeFrame(RenderTreeFrame frame)\n    => frame.FrameType == RenderTreeFrameType.Attribute;","tryCatchPattern":null,"preventionTips":["Prefer the typed AddAttribute overloads over the frame-based overload.","If using raw frames, always verify frame.FrameType == Attribute first.","Document the contract for any method accepting RenderTreeFrame parameters.","Unit test custom rendering code with various frame types."],"tags":["blazor","rendertreebuilder","attributes","rendertreeframe","validation"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}