dotnet/aspnetcore · error · Error
Circuit options have already been configured.
Error message
Circuit options have already been configured.
What it means
Thrown by setCircuitOptions in Boot.Server.Common.ts if the module-level 'options' variable is already set. Circuit options are a singleton: they are configured once during boot and reused for the lifetime of the page. A second call means boot/initialization logic ran twice.
Source
Thrown at src/Components/Web.JS/src/Boot.Server.Common.ts:27
import { DefaultReconnectionHandler } from './Platform/Circuits/DefaultReconnectionHandler';
import { discoverServerPersistedState, ServerComponentDescriptor } from './Services/ComponentDescriptorDiscovery';
import { JSEventRegistry } from './Services/JSEventRegistry';
import { fetchAndInvokeInitializers } from './JSInitializers/JSInitializers.Server';
import { RootComponentManager } from './Services/RootComponentManager';
import { WebRendererId } from './Rendering/WebRendererId';
import { addDispatchEventMiddleware } from './Rendering/WebRendererInteropMethods';
let initializersPromise: Promise<void> | undefined;
let appState: string;
let circuit: CircuitManager;
let options: CircuitStartOptions;
let logger: ConsoleLogger;
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;View on GitHub (pinned to 294cab2f9b)
Solutions
- Call Blazor.start() at most once; guard with if (!Blazor._internal.isStarted) or check hasStartedServer() before starting.
- Disable auto-start (do not include the autostart flag / set window.Blazor to disable) when you call start() manually.
- Ensure JS initializers only read options, not re-configure them; route all option changes through the single boot call.
- Remove duplicate <script> references to blazor.server.js / blazor.web.js.
Example fix
// before: double configuration
Blazor.start({ circuit: { ... } });
Blazor.start({ circuit: { ... } }); // throws
// after: start once
if (!window.__blazorStarted) {
window.__blazorStarted = true;
Blazor.start({ circuit: { ... } });
} Defensive patterns
Strategy: validation
Validate before calling
// No public 'optionsConfigured' flag is exported; guard with a window flag.
function configureCircuitOnce(opts: Partial<CircuitStartOptions>) {
if ((window as any).__circuitOptionsConfigured) return;
(window as any).__circuitOptionsConfigured = true;
Blazor.start({ circuit: opts });
} Type guard
declare module './Boot.Server.Common' {
function setCircuitOptions(p: Promise<Partial<CircuitStartOptions>>): void;
}
// call only when not yet started
function shouldConfigure(): boolean {
return !(window as any).__circuitOptionsConfigured;
} Try / catch
try {
setCircuitOptions(initializersReady);
} catch (e) {
if (/already been configured/.test((e as Error).message)) {
// idempotent no-op
} else throw e;
} Prevention
- Call Blazor.start() exactly once per page load.
- Disable autostart when starting manually.
- Do not re-configure circuit options from JS initializers.
- Track a window-level started flag in your boot script.
When it happens
Trigger: Calling Blazor.start({ circuit: {...} }) more than once, or a JS initializer that also calls setCircuitOptions, or Boot.Web.ts's onInitialDomContentLoaded running twice (e.g. two DOMContentLoaded listeners or a double boot).
Common situations: Manually invoking Blazor.start() in script while auto-start is also enabled; an HMR/hot-reload cycle re-running the boot module; a custom hosting page that calls start() then re-imports the bundle; misconfigured initializers that mutate circuit options twice.
Related errors
- Blazor Server has already started.
- Blazor has already started.
- WebAssembly options have already been configured.
- Cannot start the circuit until Blazor Server has started.
- Blazor has already started.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/527ca53ac2e2d946.
Report an issue: GitHub.