dotnet/aspnetcore · error

Dynamic root components have not been enabled in this…

Error message

Dynamic root components have not been enabled in this application.

What it means

Thrown by getRequiredManager when the module-level manager is unset, i.e. enableJSRootComponents was never called for this page. Dynamic root component APIs (add) need a live .NET DotNetObjectReference to invoke AddRootComponent; without it the operation cannot proceed. This typically means JS component initialization was not wired up.

Solutions

  1. Await Blazor.start() before calling rootComponents.add.
  2. Ensure the app is a Blazor Server or WebAssembly interactive host (JS root components require an interactive renderer).
  3. Move the registration into a JSInitializer that the framework calls after startup.
  4. Verify AddComponent support is enabled in the .NET host configuration.

Example fix

// before (throws)
Blazor.rootComponents.add(el, 'MyComponent', {});

// after
await Blazor.start();
await Blazor.rootComponents.add(el, 'MyComponent', {});
Defensive patterns

Strategy: validation

Validate before calling

if (!Blazor.rootComponents) {
  throw new Error('JS root components are not enabled; check your host configuration.');
}
await Blazor.start();
await Blazor.rootComponents.add(el, id, params);

Try / catch

try {
  await Blazor.rootComponents.add(el, id, params);
} catch (e) {
  if (/not been enabled/.test(String(e?.message))) {
    await Blazor.start();
    await Blazor.rootComponents.add(el, id, params);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling Blazor.rootComponents.add before Blazor has started; using add in an app that did not register JSComponentInitializer callbacks; calling during prerender before the circuit is established.

Common situations: Calling add in a script that runs before Blazor.start resolves; an app not configured for JSRootComponents; an early DOMContentLoaded handler racing the framework.

Related errors


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

Appendix: source

Thrown at src/Components/Web.JS/src/Rendering/JSRootComponents.ts:158

  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];
        initializerFunc(componentIdentifier, parameters);
      }
    }

    hasInitializedJsComponents = true;
  }
}

function getRequiredManager(): DotNet.DotNetObject {
  if (!manager) {
    throw new Error('Dynamic root components have not been enabled in this application.');
  }

  return manager;
}

// Keep in sync with equivalent in JSComponentConfigurationStore.cs
// These are an internal implementation detail not exposed in the registration APIs.
export type JSComponentParametersByIdentifier = { [identifier: string]: JSComponentParameter[] };
export type JSComponentIdentifiersByInitializer = { [initializer: string]: string[] };

// The following is public API
export interface JSComponentInitializerCallback {
  (identifier: string, parameters: JSComponentParameter[]): void;
}

export interface JSComponentParameter {
  name: string;
  type: JSComponentParameterType;

View on GitHub (pinned to 3600ca084e)