dotnet/aspnetcore · error · InvalidOperationException
SectionContent requires that 'SectionName' and 'SectionId' c
Error message
SectionContent requires that 'SectionName' and 'SectionId' cannot both have non-null values.
What it means
SectionContent is the provider side of Blazor's content-sharing mechanism; it identifies its target outlet by exactly one of SectionName (string) or SectionId (object). SetParametersAsync throws InvalidOperationException when both are non-null because the matching identifier is ambiguous. This is an invariant enforced on every parameter set, so it fires even if the two values would resolve to the same outlet.
Source
Thrown at src/Components/Components/src/Sections/SectionContent.cs:56
[Parameter] public RenderFragment? ChildContent { get; set; }
void IComponent.Attach(RenderHandle renderHandle)
{
SectionRenderMode = renderHandle.RenderMode;
_registry = renderHandle.SectionRegistry;
}
Task IComponent.SetParametersAsync(ParameterView parameters)
{
// We are not using parameters.SetParameterProperties(this)
// because IsDefaultContent is internal property and not a parameter
SetParameterValues(parameters);
object? identifier;
if (SectionName is not null && SectionId is not null)
{
throw new InvalidOperationException($"{nameof(SectionContent)} requires that '{nameof(SectionName)}' and '{nameof(SectionId)}' cannot both have non-null values.");
}
else if (SectionName is not null)
{
identifier = SectionName;
}
else if (SectionId is not null)
{
identifier = SectionId;
}
else
{
throw new InvalidOperationException($"{nameof(SectionContent)} requires a non-null value either for '{nameof(SectionName)}' or '{nameof(SectionId)}'.");
}
if (!object.Equals(identifier, _registeredIdentifier) || IsDefaultContent != _registeredIsDefaultContent)
{
if (_registeredIdentifier is not null)
{View on GitHub (pinned to 294cab2f9b)
Solutions
- Remove one of the two attributes so only SectionName OR SectionId is set.
- If migrating identifiers, delete the stale attribute rather than commenting it out — Razor still binds commented-style typos in code blocks.
- Audit any splatted ParameterView/Dictionary<string,object> passed to SectionContent to ensure it does not contain both keys.
- Use SectionId with a static object instance (e.g., a readonly field) when you need compile-time uniqueness instead of the string key.
Example fix
// before
<SectionContent SectionName="header" SectionId="@MyHeaderId">
<Header />
</SectionContent>
// after
<SectionContent SectionId="@MyHeaderId">
<Header />
</SectionContent> Defensive patterns
Strategy: validation
Validate before calling
// Validate before rendering the SectionContent
@if (!string.IsNullOrEmpty(sectionName) ^ sectionId is not null)
{
<SectionContent SectionName="@sectionName" SectionId="@sectionId">
@ChildContent
</SectionContent>
}
else
{
<div class="alert alert-danger">SectionContent needs exactly one identifier.</div>
} Type guard
// Exactly one identifier must be set
static bool HasSingleSectionIdentifier(string? name, object? id) =>
(name is not null) ^ (id is not null); Try / catch
// Razor cannot easily catch render-time exceptions; instead gate the component.
// If rendering imperatively via RenderTreeBuilder, validate first:
object? identifier = sectionName ?? sectionId;
if (HasSingleSectionIdentifier(sectionName, sectionId))
{
builder.OpenComponent<SectionContent>(0);
if (sectionName is not null) builder.AddAttribute(1, "SectionName", sectionName);
if (sectionId is not null) builder.AddAttribute(2, "SectionId", sectionId);
builder.CloseComponent();
} Prevention
- Adopt one identifier convention per app (SectionName for simple, SectionId for type-safe) and lint against the other.
- Never splat attribute dictionaries into SectionContent without filtering keys.
- Add a unit test asserting every SectionContent usage sets exactly one identifier.
When it happens
Trigger: Declaring <SectionContent SectionName="header" SectionId="@someObj"> in markup, or programmatically passing both parameters when constructing the component. The check at SectionContent.cs:54 is hit on the first SetParametersAsync call and on every subsequent re-render that supplies both values.
Common situations: Copy-pasting a SectionContent and forgetting to remove one identifier; migrating from SectionName (string) to SectionId (object) and leaving the old attribute; a parent component passing both via splatting dictionaries.
Related errors
- SectionContent requires a non-null value either for 'Section
- Unknown parameter '{param.Name}'
- SectionOutlet requires that 'SectionName' and 'SectionId' ca
- SectionOutlet requires a non-null value either for 'SectionN
- Unable to set property '{parameterName}' on object of type '
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/2b7b843be8b813d4.
Report an issue: GitHub.