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
- Ensure AddAttribute(sequence, name) (valueless) is only called after OpenElement and before CloseElement.
- Use the three-argument overload AddAttribute(sequence, name, value) for component parameters.
- Check the call ordering in custom RenderTreeBuilder code: OpenElement must precede valueless attribute calls.
- 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
- Always call OpenElement before using the valueless AddAttribute(int, string) overload.
- Use the three-argument AddAttribute(int, string, object) overload for component parameters.
- In manual render code, maintain strict ordering: OpenElement -> AddAttribute -> CloseElement.
- Add code comments documenting when valueless attributes are valid.
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
- No preceding attribute frame exists.
- Incorrect frame type: '{prevFrame.FrameTypeField}'
- Cannot set a key outside the scope of a component or element
- The FrameType must be Attribute.
- Cannot set a key on a frame of type {parentFrame.FrameTypeFi
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/75ed9813dcf9ad95.
Report an issue: GitHub.