dotnet/aspnetcore · error · Error
Blazor has already started.
Error message
Blazor has already started.
What it means
Thrown by boot() in Boot.WebAssembly.ts when the module-level 'started' flag is already true. This is the top-level entrypoint guard for the standalone Blazor WebAssembly boot path; re-entry would re-discover components, re-set options, and re-run startWebAssembly.
Solutions
- Call Blazor.start() at most once per page; remove duplicate calls.
- Disable autostart and start manually from a single location when you need control.
- Memoize the boot promise so retries reuse the first invocation.
- Audit bundler/HMR and the host HTML for double-inclusion of the boot script.
Example fix
// before
function safeRestart() { Blazor.start(); } // each call throws
// after
let p;
function safeRestart() { return p ?? (p = Blazor.start()); } Defensive patterns
Strategy: validation
Validate before calling
// Guard WebAssembly boot at the call site.
let wasmStarted;
function startWasmOnce(opts) {
if (wasmStarted) return wasmStarted;
wasmStarted = Blazor.start(opts);
return wasmStarted;
} Try / catch
try {
await Blazor.start(opts);
} catch (e) {
if (/already started/.test(e.message)) return;
throw e;
} Prevention
- Disable autostart when calling Blazor.start() manually.
- Memoize the boot promise at a single entrypoint.
- Include the boot script exactly once in index.html.
- Prefer page reload over re-boot for recovery from partial failures.
When it happens
Trigger: Calling Blazor.start() in a WebAssembly app more than once per page, or having the boot module evaluated twice.
Common situations: Autostart plus a manual Blazor.start(); a retry/recovery routine that re-invokes boot after a partially successful start; HMR or bundler duplication evaluating Boot.WebAssembly.ts twice; a host page that includes blazor.webassembly.js more than once.
Related errors
- Blazor WebAssembly has already started.
- WebAssembly options have already been configured.
- Blazor has already started.
- Blazor has already started.
- Blazor has already started.
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/fa9045b98534142b.
Report an issue: GitHub.
Appendix: source
Thrown at src/Components/Web.JS/src/Boot.WebAssembly.ts:21
/* eslint-disable array-element-newline */
import { Blazor } from './GlobalExports';
import { shouldAutoStart } from './BootCommon';
import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions';
import { setWebAssemblyOptions, startWebAssembly } from './Boot.WebAssembly.Common';
import { WebAssemblyComponentDescriptor, discoverComponents, discoverWebAssemblyOptions } from './Services/ComponentDescriptorDiscovery';
import { DotNet } from '@microsoft/dotnet-js-interop';
import { InitialRootComponentsList } from './Services/InitialRootComponentsList';
import { JSEventRegistry } from './Services/JSEventRegistry';
import { printErr } from './Platform/Mono/MonoPlatform';
type BlazorWebAssemblyStartOptions = Partial<WebAssemblyStartOptions> & { webAssembly?: Partial<WebAssemblyStartOptions> };
let started = false;
async function boot(options?: BlazorWebAssemblyStartOptions): Promise<void> {
if (started) {
throw new Error('Blazor has already started.');
}
started = true;
// Accept the `webAssembly` property from the blazor.web.js options format
const normalizedOptions = options?.webAssembly ?? options ?? {};
setWebAssemblyOptions(Promise.resolve(normalizedOptions));
JSEventRegistry.create(Blazor);
const webAssemblyComponents = discoverComponents(document, 'webassembly') as WebAssemblyComponentDescriptor[];
const webAssemblyOptions = discoverWebAssemblyOptions(document);
const components = new InitialRootComponentsList(webAssemblyComponents);
await startWebAssembly(components, webAssemblyOptions);
}
Blazor.start = boot;
window['DotNet'] = DotNet;
View on GitHub (pinned to 3600ca084e)