dotnet/aspnetcore · error · InvalidOperationException
Cannot set a key outside the scope of a component or element
Error message
Cannot set a key outside the scope of a component or element.
What it means
RenderTreeBuilder.SetKey assigns a @key to the current open element or component. It locates the current parent frame index via GetCurrentParentFrameIndex(); if there is no open element or component (the frame stack is empty or the current scope is not an element/component), it throws InvalidOperationException. Keys can only be set within the scope of an element or component frame.
Source
Thrown at src/Components/Components/src/Rendering/RenderTreeBuilder.cs:540
}
/// <summary>
/// Assigns the specified key value to the current element or component.
/// </summary>
/// <param name="value">The value for the key.</param>
public void SetKey(object? value)
{
if (value == null)
{
// Null is equivalent to not having set a key, which is valuable because Razor syntax doesn't have an
// easy way to have conditional directive attributes
return;
}
var parentFrameIndex = GetCurrentParentFrameIndex();
if (!parentFrameIndex.HasValue)
{
throw new InvalidOperationException("Cannot set a key outside the scope of a component or element.");
}
var parentFrameIndexValue = parentFrameIndex.Value;
ref var parentFrame = ref _entries.Buffer[parentFrameIndexValue];
switch (parentFrame.FrameTypeField)
{
case RenderTreeFrameType.Element:
parentFrame.ElementKeyField = value; // It's a ref var, so this writes to the array
break;
case RenderTreeFrameType.Component:
parentFrame.ComponentKeyField = value; // It's a ref var, so this writes to the array
break;
default:
throw new InvalidOperationException($"Cannot set a key on a frame of type {parentFrame.FrameTypeField}.");
}
}
private void OpenComponentUnchecked(int sequence, [DynamicallyAccessedMembers(Component)] Type componentType)View on GitHub (pinned to 294cab2f9b)
Solutions
- Ensure SetKey is called after OpenElement/OpenComponent and before CloseElement/CloseComponent.
- In Razor, place @key as an attribute on an element or component, not as a standalone directive.
- Check the call ordering: OpenElement -> ... -> SetKey -> CloseElement.
- Remove the @key directive if it's not attached to a specific element or component.
Example fix
<!-- before (Razor) -->
@key("myKey")
<div>Hello</div>
<!-- after -->
<div @key="myKey">Hello</div> Defensive patterns
Strategy: validation
Validate before calling
// In Razor, ensure @key is on an element or component
// In manual code, ensure OpenElement/OpenComponent precedes SetKey
builder.OpenElement(0, "div");
builder.SetKey("myKey");
builder.CloseElement(); Prevention
- Place @key as an attribute on an element or component tag, never standalone.
- In manual RenderTreeBuilder code, call SetKey only between Open* and Close* calls.
- Review Razor markup for @key placement during code reviews.
- Test render fragments that use @key to catch ordering errors early.
When it happens
Trigger: Calling builder.SetKey(myKey) when no element or component is currently open (i.e., at the top level of the builder, or after CloseElement/CloseComponent without a new Open). This corresponds to placing @key outside of any element or component in Razor markup.
Common situations: Placing @key before an element/component tag in Razor; calling SetKey at the top level of a render fragment; calling SetKey after closing the last frame; generated code that emits SetKey in the wrong position.
Related errors
- Valueless attributes may only be added immediately after fra
- Cannot set a key on a frame of type {parentFrame.FrameTypeFi
- More than one sibling of element '{frame.ElementNameField}'
- More than one sibling has the same key value, '{key}'. Key v
- No preceding attribute frame exists.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/8d1dfba46d7e6876.
Report an issue: GitHub.