dotnet/aspnetcore · error · ArgumentException

The FrameType must be Attribute.

Error message

The FrameType must be Attribute.

What it means

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.

Source

Thrown at src/Components/Components/src/Rendering/RenderTreeBuilder.cs:428

            AssertCanAddAttribute();
        }
    }

    /// <summary>
    /// <para>
    /// Appends a frame representing an attribute.
    /// </para>
    /// <para>
    /// The attribute is associated with the most recently added element.
    /// </para>
    /// </summary>
    /// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
    /// <param name="frame">A <see cref="RenderTreeFrame"/> holding the name and value of the attribute.</param>
    public void AddAttribute(int sequence, RenderTreeFrame frame)
    {
        if (frame.FrameTypeField != RenderTreeFrameType.Attribute)
        {
            throw new ArgumentException($"The {nameof(frame.FrameType)} must be {RenderTreeFrameType.Attribute}.");
        }

        AssertCanAddAttribute();
        frame.SequenceField = sequence;
        _entries.Append(frame);
    }

    /// <summary>
    /// Adds frames representing multiple attributes with the same sequence number.
    /// </summary>
    /// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
    /// <param name="attributes">A collection of key-value pairs representing attributes.</param>
    public void AddMultipleAttributes(int sequence, IEnumerable<KeyValuePair<string, object>>? attributes)
    {
        // Calling this up-front just to make sure we validate before mutating anything.
        AssertCanAddAttribute();

        if (attributes != null)

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Ensure any RenderTreeFrame passed to AddAttribute(int, RenderTreeFrame) has FrameType == RenderTreeFrameType.Attribute.
  2. Use the typed overloads AddAttribute(int, string, T) for normal attribute addition instead of the frame-based overload.
  3. If working with raw frames, verify frame.FrameType before calling AddAttribute.
  4. Construct attribute frames using the internal RenderTreeFrame attribute factory methods only.

Example fix

// before
var frame = RenderTreeFrame.Element(0, "div", 1); // Element frame
builder.AddAttribute(0, frame); // throws: not Attribute

// after
builder.AddAttribute(0, "class", "my-class"); // use typed overload
Defensive patterns

Strategy: validation

Validate before calling

// Validate frame type before calling AddAttribute(int, RenderTreeFrame)
static void SafeAddAttributeFrame(RenderTreeBuilder builder, int seq, RenderTreeFrame frame)
{
    if (frame.FrameType != RenderTreeFrameType.Attribute)
        throw new ArgumentException($"Frame must be Attribute, got {frame.FrameType}");
    builder.AddAttribute(seq, frame);
}

Type guard

static bool IsAttributeFrame(RenderTreeFrame frame)
    => frame.FrameType == RenderTreeFrameType.Attribute;

Prevention

When it happens

Trigger: 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.

Common situations: Custom rendering extension code that constructs RenderTreeFrame instances; test code that manually creates frames; framework-level code that reuses frame objects incorrectly.

Related errors


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