dotnet/aspnetcore · error · Error
Blazor Server has already started.
Error message
Blazor Server has already started.
What it means
Thrown by startServer when the module-level serverStartPromise is already defined. startServer is the single entry point that constructs the SignalR circuit; calling it a second time indicates the Server platform was asked to boot twice.
Source
Thrown at src/Components/Web.JS/src/Boot.Server.Common.ts:40
let serverStartPromise: Promise<void>;
let circuitStarting: Promise<boolean> | undefined;
export function setCircuitOptions(initializersReady: Promise<Partial<CircuitStartOptions>>) {
if (options) {
throw new Error('Circuit options have already been configured.');
}
initializersPromise = setOptions(initializersReady);
async function setOptions(initializers: Promise<Partial<CircuitStartOptions>>): Promise<void> {
const configuredOptions = await initializers;
options = resolveOptions(configuredOptions);
}
}
export function startServer(components: RootComponentManager<ServerComponentDescriptor>, jsEventRegistry: JSEventRegistry): Promise<void> {
if (serverStartPromise !== undefined) {
throw new Error('Blazor Server has already started.');
}
serverStartPromise = new Promise(startServerCore.bind(null, components, jsEventRegistry));
return serverStartPromise;
}
async function startServerCore(components: RootComponentManager<ServerComponentDescriptor>, jsEventRegistry: JSEventRegistry, resolve: () => void, _: any) {
await initializersPromise;
const jsInitializer = await fetchAndInvokeInitializers(options);
appState = discoverServerPersistedState(document) || '';
logger = new ConsoleLogger(options.logLevel);
circuit = new CircuitManager(components, appState, options, logger, jsEventRegistry);
addDispatchEventMiddleware((_browserRendererId, eventHandlerId, continuation) => {
logger.log(LogLevel.Debug, `Dispatching event with handler id ${eventHandlerId}.`);
continuation();View on GitHub (pinned to 294cab2f9b)
Solutions
- Guard the call site with hasStartedServer() (Boot.Server.Common.ts:178) before starting.
- Disable autostart if you start manually (omit the autostart script tag or set the relevant config flag).
- Audit JS initializers and afterStarted callbacks to ensure none re-invoke start.
- Ensure the blazor.server.js bundle is loaded exactly once per page load.
Example fix
// before
Blazor.start();
// ... later ...
Blazor.start(); // throws: already started
// after
import { hasStartedServer } from './Boot.Server.Common';
if (!hasStartedServer()) {
Blazor.start();
} Defensive patterns
Strategy: validation
Validate before calling
import { hasStartedServer } from './Boot.Server.Common';
function startServerOnce(components: any, events: any) {
if (hasStartedServer()) return Promise.resolve();
return startServer(components, events);
} Type guard
import { hasStartedServer } from './Boot.Server.Common';
function serverIsStarted(): boolean {
return hasStartedServer();
} Try / catch
try {
await Blazor.start();
} catch (e) {
if (/already started/.test((e as Error).message)) {
// benign: already running
} else throw e;
} Prevention
- Guard with hasStartedServer() before calling startServer or Blazor.start().
- Disable autostart when booting manually.
- Audit afterStarted callbacks so none re-invoke boot.
- Load blazor.server.js once per page.
When it happens
Trigger: Invoking Blazor.start() twice on a Server-rendered app, or two boot paths both calling startServer (e.g. an initializer that re-boots, or a navigation handler that re-runs boot).
Common situations: Auto-start enabled plus a manual Blazor.start() call; HMR re-running the boot module; misrouted SPA navigation that re-mounts the Blazor script; mixing blazor.server.js with a wrapper that also boots.
Related errors
- Circuit options have already been configured.
- Cannot start the circuit until Blazor Server has started.
- Blazor has already started.
- Blazor has already started.
- WebAssembly options have already been configured.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/43546a78b03dda57.
Report an issue: GitHub.