dotnet/aspnetcore · error · InvalidOperationException

{nameof(SectionContent)} requires that '{nameof(SectionName)

Error message

{nameof(SectionContent)} requires that '{nameof(SectionName)}' and '{nameof(SectionId)}' cannot both have non-null values.

What it means

SectionContent identifies the section it supplies content for by either a string name (SectionName) or an object identifier (SectionId), but not both. The two are mutually exclusive identification modes; if both are non-null the component cannot decide which to register under, so SetParametersAsync throws InvalidOperationException. The check runs before the registry is touched, so no partial state is committed.

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 3600ca084e)

Solutions

  1. Pick one identifier style and remove the other attribute from <SectionContent>.
  2. Use SectionName for static, declarative sections; use SectionId (a shared object instance) for sections resolved across components without magic strings.
  3. If the design needs both, split into two SectionContent elements targeted at different outlets.

Example fix

// before
<SectionContent SectionName="banner" SectionId="@myId">...</SectionContent>
// after — name only
<SectionContent SectionName="banner">...</SectionContent>
Defensive patterns

Strategy: validation

Validate before calling

// In markup, set exactly one identifier. Programmatic check:
if (sectionName is not null && sectionId is not null)
    throw new InvalidOperationException("Set SectionName XOR SectionId, not both.");

Type guard

static bool IsExclusiveSectionIdentifier(string? name, object? id)
    => (name is not null) ^ (id is not null);

Prevention

When it happens

Trigger: Setting both SectionName="foo" and SectionId="@someObject" on the same <SectionContent> element. The properties are distinct [Parameter]s that are both populated from markup.

Common situations: Switching from name-based to id-based sections and leaving the old attribute in markup; copy-pasting from samples that use different identification styles; auto-completion adding both attributes.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/79ee9f3e3c510493. Report an issue: GitHub.