dotnet/aspnetcore · error · Error

Blazor WebAssembly has not initialized.

Error message

Blazor WebAssembly has not initialized.

What it means

Thrown by updateWebAssemblyRootComponents when startPromise exists but Blazor._internal.updateRootComponents is not yet defined. This means the WebAssembly runtime started loading but the .NET-side updateRootComponents handler has not been registered yet (the runtime is mid-initialization, before callEntryPoint wires up _internal).

Solutions

  1. Let the framework schedule updates via scheduleAfterStarted (await startPromise and the afterStarted callbacks) rather than calling updateRootComponents directly.
  2. Ensure your code runs inside an afterStarted callback so _internal.updateRootComponents is guaranteed registered.
  3. If invoking manually, await Blazor.start() fully before issuing updates.
  4. Check for blocking JS initializers that delay callEntryPoint.

Example fix

// before — calling before runtime registered the callback
Blazor._internal.updateRootComponents(ops, state); // _internal.updateRootComponents is undefined

// after — wait until afterStarted has run
Blazor.start().then(() => {
  // _internal.updateRootComponents is now registered
  Blazor._internal.updateRootComponents(ops, state);
});
Defensive patterns

Strategy: validation

Validate before calling

// Only invoke updateRootComponents once the callback is registered.
function safeUpdateRootComponents(ops, state) {
  if (typeof Blazor._internal.updateRootComponents !== 'function') return;
  Blazor._internal.updateRootComponents(ops, state);
}

Type guard

function isUpdateRootComponentsReady() {
  return typeof Blazor._internal?.updateRootComponents === 'function';
}

Try / catch

try {
  Blazor._internal.updateRootComponents(ops, state);
} catch (e) {
  if (/has not initialized/.test(e.message)) {
    // schedule via afterStarted instead
  } else throw e;
}

Prevention

When it happens

Trigger: Invoking updateWebAssemblyRootComponents during the window between startWebAssembly() resolving startPromise's existence and platform.start()/callEntryPoint() completing — i.e. the runtime is up enough to call but _internal.updateRootComponents is still unregistered.

Common situations: Enhanced navigation or hot-reload firing very early in startup; manual calls to the API during boot; a slow initializer blocking callEntryPoint; partial initialization where platform load succeeded but managed code has not registered its callbacks.

Related errors


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

Appendix: source

Thrown at src/Components/Web.JS/src/Boot.WebAssembly.Common.ts:250

  })();
  return platformLoadPromise;
}

export function hasStartedLoadingWebAssemblyPlatform(): boolean {
  return platformLoadPromise !== undefined;
}

export function hasLoadedWebAssemblyPlatform(): boolean {
  return loadedWebAssemblyPlatform;
}

export function updateWebAssemblyRootComponents(operations: string, webAssemblyState: string): void {
  if (!startPromise) {
    throw new Error('Blazor WebAssembly has not started.');
  }

  if (!Blazor._internal.updateRootComponents) {
    throw new Error('Blazor WebAssembly has not initialized.');
  }

  if (!started) {
    scheduleAfterStarted(operations, webAssemblyState);
  } else {
    Blazor._internal.updateRootComponents(operations, webAssemblyState);
  }
}

async function scheduleAfterStarted(operations: string, webAssemblyState: string): Promise<void> {
  await startPromise;

  if (!Blazor._internal.updateRootComponents) {
    throw new Error('Blazor WebAssembly has not initialized.');
  }

  Blazor._internal.updateRootComponents(operations, webAssemblyState);
}

View on GitHub (pinned to 3600ca084e)