dotnet/aspnetcore · error · InvalidOperationException

Component reference captures may only be added as children o

Error message

Component reference captures may only be added as children of frames of type Component

What it means

Thrown by RenderTreeBuilder.AddComponentReferenceCapture (the frame emitted for a child-component @ref capture) when GetCurrentParentFrameIndex() returns null — the _openElementIndices stack is empty, so there is no enclosing frame of any kind. A component-reference capture must be a child of the component it references.

Source

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

        {
            throw new InvalidOperationException($"Element reference captures may only be added as children of frames of type {RenderTreeFrameType.Element}");
        }

        _entries.AppendElementReferenceCapture(sequence, elementReferenceCaptureAction);
        _lastNonAttributeFrameType = RenderTreeFrameType.ElementReferenceCapture;
    }

    /// <summary>
    /// Appends a frame representing an instruction to capture a reference to the parent component.
    /// </summary>
    /// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
    /// <param name="componentReferenceCaptureAction">An action to be invoked whenever the reference value changes.</param>
    public void AddComponentReferenceCapture(int sequence, Action<object> componentReferenceCaptureAction)
    {
        var parentFrameIndex = GetCurrentParentFrameIndex();
        if (!parentFrameIndex.HasValue)
        {
            throw new InvalidOperationException(ComponentReferenceCaptureInvalidParentMessage);
        }

        var parentFrameIndexValue = parentFrameIndex.Value;
        if (_entries.Buffer[parentFrameIndexValue].FrameTypeField != RenderTreeFrameType.Component)
        {
            throw new InvalidOperationException(ComponentReferenceCaptureInvalidParentMessage);
        }

        _entries.AppendComponentReferenceCapture(sequence, componentReferenceCaptureAction, parentFrameIndexValue);
        _lastNonAttributeFrameType = RenderTreeFrameType.ComponentReferenceCapture;
    }

    /// <summary>
    /// Adds a frame indicating the render mode on the enclosing component frame.
    /// </summary>
    /// <param name="renderMode">The <see cref="IComponentRenderMode"/>.</param>
    public void AddComponentRenderMode(IComponentRenderMode? renderMode)
    {

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Wrap the AddComponentReferenceCapture call inside OpenComponent(...)/CloseComponent() for the component it captures.
  2. If the component open is conditional, make the capture conditional too (guard both with the same if).
  3. Remove capture calls that no longer correspond to any OpenComponent.

Example fix

// before
builder.AddComponentReferenceCapture(1, r => _comp = r);
builder.OpenComponent<MyComp>(0);
builder.CloseComponent();

// after
builder.OpenComponent<MyComp>(0);
builder.AddComponentParameter(1, ...);
builder.AddComponentReferenceCapture(2, r => _comp = r);
builder.CloseComponent();
Defensive patterns

Strategy: validation

Validate before calling

// No public accessor for parent existence. Guarantee the capture is inside OpenComponent by structure.
bool _componentOpen = false;
void Render(RenderTreeBuilder b) {
    b.OpenComponent<MyComp>(0); _componentOpen = true;
    if (_componentOpen) b.AddComponentReferenceCapture(1, r => _comp = r);
    _componentOpen = false; b.CloseComponent();
}

Prevention

When it happens

Trigger: Calling builder.AddComponentReferenceCapture(seq, action) at the top level of a RenderFragment with no preceding Open*/OpenComponent. Equivalent to a @ref on a component placed outside any parent scope in hand-built tree code.

Common situations: Hand-written RenderFragment that appends the capture before OpenComponent; logic that conditionally opens a component but unconditionally runs the capture; a stray capture left after deleting an OpenComponent call.

Related errors


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