dotnet/aspnetcore · error · InvalidOperationException

No preceding attribute frame exists.

Error message

No preceding attribute frame exists.

What it means

RenderTreeBuilder.SetUpdatesAttributeName annotates the most recently appended frame as an event handler whose execution updates a specific attribute. It requires at least one frame to have been added (_entries.Count > 0). If called when no frames exist at all, it throws InvalidOperationException. This typically indicates the method was called before any content was added to the builder.

Source

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

    }

    /// <summary>
    /// <para>
    /// Indicates that the preceding attribute represents an event handler
    /// whose execution updates the attribute with name <paramref name="updatesAttributeName"/>.
    /// </para>
    /// <para>
    /// This information is used by the rendering system to determine whether
    /// to accept a value update for the other attribute when receiving a
    /// call to the event handler.
    /// </para>
    /// </summary>
    /// <param name="updatesAttributeName">The name of another attribute whose value can be updated when the event handler is executed.</param>
    public void SetUpdatesAttributeName(string updatesAttributeName)
    {
        if (_entries.Count == 0)
        {
            throw new InvalidOperationException("No preceding attribute frame exists.");
        }

        ref var prevFrame = ref _entries.Buffer[_entries.Count - 1];
        if (prevFrame.FrameTypeField != RenderTreeFrameType.Attribute)
        {
            throw new InvalidOperationException($"Incorrect frame type: '{prevFrame.FrameTypeField}'");
        }

        prevFrame.AttributeEventUpdatesAttributeNameField = updatesAttributeName;
    }

    /// <summary>
    /// Appends a frame representing a child component.
    /// </summary>
    /// <typeparam name="TComponent">The type of the child component.</typeparam>
    /// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
    public void OpenComponent<[DynamicallyAccessedMembers(Component)] TComponent>(int sequence) where TComponent : notnull, IComponent
        => OpenComponentUnchecked(sequence, typeof(TComponent));

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Ensure at least one frame (typically an event handler attribute frame) has been added before calling SetUpdatesAttributeName.
  2. Call SetUpdatesAttributeName immediately after the attribute it annotates, not before any frames exist.
  3. Review the call ordering: OpenElement -> AddAttribute (event handler) -> SetUpdatesAttributeName -> CloseElement.
  4. If this is from generated code, check that the @bind directive is placed on a valid element with a preceding attribute.

Example fix

// before
builder.SetUpdatesAttributeName("value"); // no frames yet -> throws
builder.OpenElement(0, "input");

// after
builder.OpenElement(0, "input");
builder.AddAttribute(1, "oninput", handler);
builder.SetUpdatesAttributeName("value"); // annotates the oninput frame
Defensive patterns

Strategy: validation

Validate before calling

// The builder checks _entries.Count == 0; guard before calling
// No public API to check this; ensure correct call ordering in your code
// Always add at least one frame (an attribute) before calling SetUpdatesAttributeName

Prevention

When it happens

Trigger: Calling builder.SetUpdatesAttributeName("value") as the first operation on a fresh RenderTreeBuilder, or after the builder's buffer has been cleared/reset. This is generated by the Razor compiler for @bind directives and is rarely called manually, but can be triggered by incorrect manual RenderTreeBuilder code.

Common situations: Incorrect manual RenderTreeBuilder sequencing; code generated by a custom source generator that emits SetUpdatesAttributeName in the wrong position; calling SetUpdatesAttributeName after CloseElement/CloseComponent cleared the context.

Related errors


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