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

  1. Remove one of the two attributes so only SectionName OR SectionId is set.
  2. If migrating identifiers, delete the stale attribute rather than commenting it out — Razor still binds commented-style typos in code blocks.
  3. Audit any splatted ParameterView/Dictionary<string,object> passed to SectionContent to ensure it does not contain both keys.
  4. 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

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


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