dotnet/aspnetcore · error · InvalidOperationException
Attributes may only be added immediately after frames of typ
Error message
Attributes may only be added immediately after frames of type Element or Component
What it means
Thrown by the private AssertCanAddAttribute guard invoked by AddAttribute/AddMultipleAttributes. Attributes are only valid immediately after an Element or Component frame (the last non-attribute frame must be Element or Component); text, markup, region, reference-capture, and named-event frames cannot receive attributes.
Source
Thrown at src/Components/Components/src/Rendering/RenderTreeBuilder.cs:724
_lastNonAttributeFrameType = RenderTreeFrameType.Region;
}
/// <summary>
/// Marks a previously appended region frame as closed. Calls to this method
/// must be balanced with calls to <see cref="OpenRegion(int)"/>.
/// </summary>
public void CloseRegion()
{
var indexOfEntryBeingClosed = _openElementIndices.Pop();
_entries.Buffer[indexOfEntryBeingClosed].RegionSubtreeLengthField = _entries.Count - indexOfEntryBeingClosed;
}
private void AssertCanAddAttribute()
{
if (_lastNonAttributeFrameType != RenderTreeFrameType.Element
&& _lastNonAttributeFrameType != RenderTreeFrameType.Component)
{
throw new InvalidOperationException($"Attributes may only be added immediately after frames of type {RenderTreeFrameType.Element} or {RenderTreeFrameType.Component}");
}
}
private void AssertCanAddComponentParameter()
{
if (_lastNonAttributeFrameType != RenderTreeFrameType.Component)
{
throw new InvalidOperationException($"Component parameters may only be added immediately after frames of type {RenderTreeFrameType.Component}");
}
}
private int? GetCurrentParentFrameIndex()
=> _openElementIndices.Count == 0 ? (int?)null : _openElementIndices.Peek();
private RenderTreeFrameType? GetCurrentParentFrameType()
{
var parentIndex = GetCurrentParentFrameIndex();
return parentIndex.HasValueView on GitHub (pinned to 294cab2f9b)
Solutions
- Emit all AddAttribute calls directly after OpenElement/OpenComponent and before any child content/text.
- If attributes are computed after content, restructure so attributes are added first or re-open the element/component.
- Check that no AddContent/AddMarkupContent/OpenRegion runs between the open and the attribute.
Example fix
// before builder.OpenElement(0, "div"); builder.AddContent(1, "hello"); builder.AddAttribute(2, "class", "x"); builder.CloseElement(); // after builder.OpenElement(0, "div"); builder.AddAttribute(1, "class", "x"); builder.AddContent(2, "hello"); builder.CloseElement();
Defensive patterns
Strategy: validation
Validate before calling
// Emit attributes immediately after OpenElement/OpenComponent and before any content frame.
void RenderDiv(RenderTreeBuilder b) {
b.OpenElement(0, "div");
b.AddAttribute(1, "class", _cls); // attributes first
b.AddContent(2, _text); // then content
b.CloseElement();
} Prevention
- Order frames: open -> attributes -> children -> close; never interleave attributes with content.
- In loops building attributes, keep them contiguous before the first child frame.
- Use AddContent/AddMarkupContent only after all attributes are added.
When it happens
Trigger: Calling builder.AddAttribute(seq, name, value) after AddContent/AddMarkupContent/OpenRegion/AddElementReferenceCapture/AddNamedEvent — i.e., when _lastNonAttributeFrameType is not Element or Component. In .razor this maps to an attribute appearing after literal text or inside a region instead of directly on the tag.
Common situations: A misplaced attribute in hand-written RenderFragment after a text node; a conditional that emits text before the attribute; code generation that interleaves attributes with content frames.
Related errors
- Element reference captures may only be added as children of
- Component reference captures may only be added as children o
- Named events may only be added as children of frames of type
- Component parameters may only be added immediately after fra
- Object of type '{targetType.FullName}' has a property matchi
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/efbf81741734568b.
Report an issue: GitHub.