dotnet/aspnetcore · error · Error
Dynamic root components have already been enabled.
Error message
Dynamic root components have already been enabled.
What it means
Thrown by enableJSRootComponents when a manager is already registered for a different rendererId. Dynamic JS root components are tied to a single renderer type (Server or WebAssembly); enabling them from a second, different renderer in the same page is a multi-host scenario the framework does not support.
Source
Thrown at src/Components/Web.JS/src/Rendering/JSRootComponents.ts:129
for (const jsEventCallbackWrapper of this._jsEventCallbackWrappers.values()) {
jsEventCallbackWrapper.dispose();
}
}
}
}
// Called by the framework
export function enableJSRootComponents(
rendererId: number,
managerInstance: DotNet.DotNetObject,
jsComponentParameters: JSComponentParametersByIdentifier,
jsComponentInitializers: JSComponentIdentifiersByInitializer
): void {
if (manager && currentRendererId !== rendererId) {
// A different renderer type (e.g., Server vs WebAssembly) is trying to enable JS root components.
// This is a multi-host scenario which is not supported for dynamic root components.
throw new Error('Dynamic root components have already been enabled.');
}
// When the same renderer type re-enables (e.g., circuit restart or new circuit on same page),
// accept the new manager. The old manager's DotNetObjectReference is no longer valid anyway
// because the old circuit is gone. We don't dispose the old manager - doing so would cause
// JSDisconnectedException because the circuit that created it no longer exists.
currentRendererId = rendererId;
manager = managerInstance;
jsComponentParametersByIdentifier = jsComponentParameters;
if (!hasInitializedJsComponents) {
// Call the registered initializers. This is an arbitrary subset of the JS component types that are registered
// on the .NET side - just those of them that require some JS-side initialization (e.g., to register them
// as custom elements).
for (const [initializerIdentifier, componentIdentifiers] of Object.entries(jsComponentInitializers)) {
const initializerFunc = DotNet.findJSFunction(initializerIdentifier, 0) as JSComponentInitializerCallback;
for (const componentIdentifier of componentIdentifiers) {
const parameters = jsComponentParameters[componentIdentifier];View on GitHub (pinned to 294cab2f9b)
Solutions
- Use only one renderer type per page for JS dynamic root components.
- Fix @rendermode configuration so a single renderer owns root components.
- If you genuinely need both, split across separate pages/iframes rather than one document.
Defensive patterns
Strategy: validation
Prevention
- Use a single renderer type (Server OR WebAssembly) for JS root components per page.
- Fix @rendermode wiring so one renderer owns root components.
- Split multi-host needs across separate pages/iframes.
When it happens
Trigger: A single page hosting both a Blazor Server and a Blazor WebAssembly root (InteractiveAuto misconfigured, or two Blazor roots of different kinds) where both try to register JS root components.
Common situations: Blazor Web App with mixed/incorrect rendermode wiring causing both Server and WebAssembly renderers to initialize JS root components; manually booting a second Blazor instance of a different kind on one page.
Related errors
- Invalid sequence number or identifier '${sequenceOrIdentifie
- initialParameters must be an object, even if empty.
- Dynamic root components have not been enabled in this applic
- The '${beforeElementSelector}' selector is not supported.
- Could not find any element matching selector '${elementSelec
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/a77960aede29a849.
Report an issue: GitHub.