dotnet/aspnetcore · error · Error
Blazor has already started.
Error message
Blazor has already started.
What it means
Thrown by boot() in Boot.WebView.ts (the .NET MAUI / WebView Blazor entry) when its module-level 'started' flag is already true. The WebView boot attaches the IPC dispatcher, starts the IPC receiver, and wires navigation — all single-shot operations for the lifetime of the WebView.
Source
Thrown at src/Components/Web.JS/src/Boot.WebView.ts:20
// The .NET Foundation licenses this file to you under the MIT license.
import { DotNet } from '@microsoft/dotnet-js-interop';
import { Blazor } from './GlobalExports';
import { shouldAutoStart } from './BootCommon';
import { internalFunctions as navigationManagerFunctions } from './Services/NavigationManager';
import { startIpcReceiver } from './Platform/WebView/WebViewIpcReceiver';
import { sendAttachPage, sendBeginInvokeDotNetFromJS, sendEndInvokeJSFromDotNet, sendByteArray, sendLocationChanged, sendLocationChanging } from './Platform/WebView/WebViewIpcSender';
import { fetchAndInvokeInitializers } from './JSInitializers/JSInitializers.WebView';
import { receiveDotNetDataStream } from './StreamingInterop';
import { WebRendererId } from './Rendering/WebRendererId';
let started = false;
export let dispatcher: DotNet.ICallDispatcher;
async function boot(): Promise<void> {
if (started) {
throw new Error('Blazor has already started.');
}
started = true;
dispatcher = DotNet.attachDispatcher({
beginInvokeDotNetFromJS: sendBeginInvokeDotNetFromJS,
endInvokeJSFromDotNet: sendEndInvokeJSFromDotNet,
sendByteArray: sendByteArray,
});
const jsInitializer = await fetchAndInvokeInitializers();
startIpcReceiver();
Blazor._internal.receiveWebViewDotNetDataStream = receiveWebViewDotNetDataStream;
navigationManagerFunctions.enableNavigationInterception(WebRendererId.WebView);
navigationManagerFunctions.listenForNavigationEvents(WebRendererId.WebView, sendLocationChanged, sendLocationChanging);
View on GitHub (pinned to 294cab2f9b)
Solutions
- Let the BlazorWebView start Blazor itself; do not call Blazor.start() manually unless you have disabled autostart.
- Ensure the WebView performs a full navigation (fresh JS context) rather than re-evaluating scripts in place.
- Guard the call with a window-level flag before invoking.
Example fix
// before <script src="_framework/blazor.webview.js" autostart></script> <script>Blazor.start();</script> <!-- throws --> // after: rely on autostart, or <script src="_framework/blazor.webview.js"></script> <script>Blazor.start();</script>
Defensive patterns
Strategy: validation
Validate before calling
function startWebViewBlazorOnce() {
if ((window as any).__blazorWebViewStarted) return Promise.resolve();
(window as any).__blazorWebViewStarted = true;
return Blazor.start();
} Type guard
function webViewBlazorStarted(): boolean {
return !!(window as any).__blazorWebViewStarted;
} Try / catch
try {
await Blazor.start();
} catch (e) {
if (/already started/.test((e as Error).message)) return;
throw e;
} Prevention
- Let the BlazorWebView start Blazor itself; do not call Blazor.start() unless autostart is off.
- Use full navigations to reset the JS context rather than re-evaluating scripts.
- Guard any manual start with a window flag.
- Avoid embedding the boot script twice in WebView HTML.
When it happens
Trigger: Calling Blazor.start() a second time inside a BlazorWebView, or the WebView reloading and re-evaluating the boot bundle while a prior boot's flag persists in the same JS context (e.g. via a non-isolated script scope).
Common situations: A native reload that does not reset the JS context; manually invoking Blazor.start() in addition to the auto-start the WebView performs; an embedded page that includes the script twice; testing harnesses that re-run boot without a fresh WebView.
Related errors
- Blazor has already started.
- Blazor has already started.
- Blazor WebAssembly has already started.
- Blazor has already started.
- Circuit options have already been configured.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/e345705e58a80dc5.
Report an issue: GitHub.