dotnet/aspnetcore · error · InvalidOperationException
More than one sibling of component '{frame.ComponentTypeFiel
Error message
More than one sibling of component '{frame.ComponentTypeField}' has the same key value, '{key}'. Key values must be unique. What it means
Blazor uses @key to track component instances across re-renders for efficient diffing and state preservation. During the diff phase, RenderTreeDiffBuilder builds a key-to-index map of sibling component frames. If two sibling components share the same non-null key, it throws InvalidOperationException because the diffing algorithm cannot unambiguously match old and new frames. Keys must be unique among siblings.
Source
Thrown at src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs:380
ThrowExceptionForDuplicateKey(key, frame);
}
result[key] = new KeyedItemInfo(existingEntry.OldIndex, newStartIndex);
}
}
newStartIndex = NextSiblingIndex(frame, newStartIndex);
}
return result;
}
private static void ThrowExceptionForDuplicateKey(object key, in RenderTreeFrame frame)
{
switch (frame.FrameTypeField)
{
case RenderTreeFrameType.Component:
throw new InvalidOperationException($"More than one sibling of component '{frame.ComponentTypeField}' has the same key value, '{key}'. Key values must be unique.");
case RenderTreeFrameType.Element:
throw new InvalidOperationException($"More than one sibling of element '{frame.ElementNameField}' has the same key value, '{key}'. Key values must be unique.");
default:
throw new InvalidOperationException($"More than one sibling has the same key value, '{key}'. Key values must be unique.");
}
}
private static object KeyValue(ref RenderTreeFrame frame)
{
switch (frame.FrameTypeField)
{
case RenderTreeFrameType.Element:
return frame.ElementKeyField;
case RenderTreeFrameType.Component:
return frame.ComponentKeyField;
default:View on GitHub (pinned to 294cab2f9b)
Solutions
- Ensure @key is bound to a property that is unique among all siblings in the same list (typically a primary key / unique identifier).
- If no natural unique key exists, combine multiple fields to form a composite unique key (e.g., key="item.Type-item.Id").
- Fix the source data if duplicate IDs are present.
- Remove @key entirely if you don't need stable identity, rather than using duplicate keys.
Example fix
<!-- before -->
@foreach (var item in items)
{
<MyComponent key="item.Category" /> <!-- Category repeats -->
}
<!-- after -->
@foreach (var item in items)
{
<MyComponent key="item.Id" /> <!-- Id is unique -->
} Defensive patterns
Strategy: validation
Validate before calling
// Validate key uniqueness before rendering
static void AssertUniqueKeys<T>(IEnumerable<T> items, Func<T, object> keySelector)
{
var seen = new HashSet<object>();
foreach (var item in items)
{
var key = keySelector(item);
if (key != null && !seen.Add(key))
throw new InvalidOperationException($"Duplicate key: {key}");
}
}
// Use: AssertUniqueKeys(items, i => i.Id); Prevention
- Always bind @key to a unique identifier (primary key, GUID).
- Add a unit test that asserts key uniqueness over the data source before rendering.
- Use composite keys (string interpolation of multiple fields) when no single unique field exists.
- Review foreach loops for correct @key binding during code reviews.
When it happens
Trigger: Rendering a list of components where @key is bound to a non-unique value. For example: foreach (var item in Items) { <MyComponent key="item.CategoryId" /> } where CategoryId repeats across items. Also triggered when @key is set to a constant or a duplicated value within the same sibling scope.
Common situations: Keying a list by a non-unique property (category, type, status) instead of a unique ID; data containing duplicate IDs from a backend bug; keying on an index that resets; copying and pasting component markup with hardcoded keys.
Related errors
- More than one sibling of element '{frame.ElementNameField}'
- More than one sibling has the same key value, '{key}'. Key v
- Invalid layout type: {layoutType.FullName} does not implemen
- Services cannot be accessed before the component is initiali
- The type '{targetType.FullName}' declares more than one para
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/56b1c5d8d185d49b.
Report an issue: GitHub.