dotnet/aspnetcore · error · InvalidOperationException

Valueless attributes may only be added immediately after fra

Error message

Valueless attributes may only be added immediately after frames of type Element

What it means

The RenderTreeBuilder.AddAttribute(int, string) overload adds a valueless (bool-true) attribute. It is only valid immediately after an Element frame (e.g., after OpenElement). The builder tracks the last non-attribute frame type and throws InvalidOperationException if it is not Element, because valueless attributes only make sense for HTML elements (e.g., <input disabled />), not components or other frame types.

Source

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

    /// <param name="textContent">Content for the new text frame.</param>
    public void AddContent(int sequence, object? textContent)
        => AddContent(sequence, textContent?.ToString());

    /// <summary>
    /// <para>
    /// Appends a frame representing a bool-valued attribute with value 'true'.
    /// </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="name">The name of the attribute.</param>
    public void AddAttribute(int sequence, string name)
    {
        if (_lastNonAttributeFrameType != RenderTreeFrameType.Element)
        {
            throw new InvalidOperationException($"Valueless attributes may only be added immediately after frames of type {RenderTreeFrameType.Element}");
        }

        _entries.AppendAttribute(sequence, name, ElementBoolTrueValue);
    }

    /// <summary>
    /// <para>
    /// Appends a frame representing a bool-valued attribute.
    /// </para>
    /// <para>
    /// The attribute is associated with the most recently added element. If the value is <c>false</c> and the
    /// current element is not a component, the frame will be omitted.
    /// </para>
    /// </summary>
    /// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
    /// <param name="name">The name of the attribute.</param>
    /// <param name="value">The value of the attribute.</param>
    public void AddAttribute(int sequence, string name, bool value)

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Ensure AddAttribute(sequence, name) (valueless) is only called after OpenElement and before CloseElement.
  2. Use the three-argument overload AddAttribute(sequence, name, value) for component parameters.
  3. Check the call ordering in custom RenderTreeBuilder code: OpenElement must precede valueless attribute calls.
  4. If targeting a component, pass the value explicitly with the typed overload.

Example fix

// before
builder.OpenComponent<MyComponent>(0);
builder.AddAttribute(1, "IsActive"); // valueless on component -> throws
builder.CloseComponent();

// after
builder.OpenComponent<MyComponent>(0);
builder.AddAttribute(1, "IsActive", true); // explicit value
builder.CloseComponent();
Defensive patterns

Strategy: validation

Validate before calling

// Validate builder state before adding valueless attribute
static void SafeAddValuelessAttribute(RenderTreeBuilder builder, int seq, string name)
{
    // The builder itself validates; this documents the contract
    // Ensure you called OpenElement first
    builder.AddAttribute(seq, name); // only valid after OpenElement
}

Prevention

When it happens

Trigger: Calling builder.AddAttribute(sequence, "disabled") without a preceding OpenElement call, or after OpenComponent. This is usually a bug in manually written render code or in a custom RenderTreeBuilder-based component. In Razor, this corresponds to writing a valueless attribute on a component instead of an element.

Common situations: Manual RenderTreeBuilder code that calls AddAttribute(int, string) before OpenElement; custom C# render methods with incorrect ordering; accidentally using the two-argument AddAttribute overload (valueless) instead of the three-argument overload.

Related errors


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