dotnet/aspnetcore · error · InvalidOperationException

There is already a subscriber to the content with the given

Error message

There is already a subscriber to the content with the given section ID '{identifier}'.

What it means

Thrown by SectionRegistry.Subscribe when a subscriber (SectionOutlet) is being registered for an identifier that already has a subscriber in the same registry. The SectionRegistry enforces a one-outlet-per-identifier invariant within a single renderer/registry, because the outlet would otherwise have ambiguous content routing.

Source

Thrown at src/Components/Components/src/Sections/SectionRegistry.cs:69

        if (index == providers.Count)
        {
            // We just removed the most recently added provider, meaning we need to change
            // the current content to that of second most recently added provider.
            var contentProvider = GetCurrentProviderContentOrDefault(providers);
            NotifyContentChangedForSubscriber(identifier, contentProvider);

            if (_subscribersByIdentifier.TryGetValue(identifier, out var subscriber))
            {
                DetectRenderModeMismatch(identifier, subscriber, contentProvider);
            }
        }
    }

    public void Subscribe(object identifier, SectionOutlet subscriber)
    {
        if (_subscribersByIdentifier.ContainsKey(identifier))
        {
            throw new InvalidOperationException($"There is already a subscriber to the content with the given section ID '{identifier}'.");
        }

        // Notify the new subscriber with any existing content.
        var provider = GetCurrentProviderContentOrDefault(identifier);
        subscriber.ContentUpdated(provider);

        _subscribersByIdentifier.Add(identifier, subscriber);

        DetectRenderModeMismatch(identifier, subscriber, provider);
    }

    public void Unsubscribe(object identifier)
    {
        if (!_subscribersByIdentifier.Remove(identifier))
        {
            throw new InvalidOperationException($"The subscriber with the given section ID '{identifier}' is already unsubscribed.");
        }

View on GitHub (pinned to 3600ca084e)

Solutions

  1. Search the component tree for duplicate <SectionOutlet> declarations sharing the same SectionName/SectionId and give each a distinct identifier.
  2. If you need the same content in multiple places, render the content in one outlet and project it elsewhere via a different mechanism (cascading value, layout reference); do not register two outlets for one identifier.
  3. For dynamic lists, derive the identifier from the item so each row's outlet is unique (e.g. SectionName=$"row-{item.Id}").
  4. Ensure that prerendering and interactive rendering are not both creating an outlet for the same identifier in the same registry scope.

Example fix

<!-- before: two outlets, one name -->
<SectionOutlet SectionName="main" />
<SectionOutlet SectionName="main" /> <!-- throws [342] -->

<!-- after: unique identifiers -->
<SectionOutlet SectionName="main" />
<SectionOutlet SectionName="secondary" />
Defensive patterns

Strategy: validation

Validate before calling

<!-- Scan the component tree at design time for duplicate SectionName/SectionId on SectionOutlet -->
@* In a test or static check, collect all SectionOutlet SectionName literals and assert uniqueness. *@
@* Razor: ensure each outlet uses a distinct identifier: *@
<SectionOutlet SectionName="@($"region-{RegionId}")" />

Type guard

// C#: validate uniqueness before render in your own component
static bool HasUniqueOutletIdentifiers(IEnumerable<object> ids) => ids.Distinct().Count() == ids.Count();

Prevention

When it happens

Trigger: Two SectionOutlet components resolve to the same identifier object (same SectionName string or equal SectionId object) and both attach to the same renderer. SectionOutlet.SetParametersAsync (line 72) calls _registry.Subscribe, which throws if _subscribersByIdentifier already contains that key.

Common situations: Placing two <SectionOutlet SectionName="main" /> in the same layout or page; using the same SectionId object instance as a key for two outlets; outlets in a loop or list that share a constant identifier; cross-render-mode confusion where both a prerendered and an interactive outlet mount for the same name.

Related errors


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